xen: make CPU hotplug functions static
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl-5000.c
index 076d356..cbc01a0 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -93,6 +92,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
        iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
                    CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
 
+       /* Set FH wait treshold to maximum (HW error during stress W/A) */
+       iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
+
+       /* enable HAP INTA to move device L1a -> L0s */
+       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+                   CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
+
        iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
 
        /* set "initialization complete" bit to move adapter
@@ -230,6 +236,16 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
                    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
                    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
 
+       /* W/A : NIC is stuck in a reset state after Early PCIe power off
+        * (PCIe power is lost before PERST# is asserted),
+        * causing ME FW to lose ownership and not being able to obtain it back.
+        */
+       iwl_grab_nic_access(priv);
+       iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+                               APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
+                               ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
+       iwl_release_nic_access(priv);
+
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
@@ -924,8 +940,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
        len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
 
        if (txq_id != IWL_CMD_QUEUE_NUM) {
-               sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id;
-               sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl;
+               sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
+               sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
 
                switch (sec_ctl & TX_CMD_SEC_MSK) {
                case TX_CMD_SEC_CCM:
@@ -964,7 +980,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
        u8 sta = 0;
 
        if (txq_id != IWL_CMD_QUEUE_NUM)
-               sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id;
+               sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id;
 
        shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr].
                                        val = cpu_to_le16(1 | (sta << 12));
@@ -1131,7 +1147,7 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
 
 static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
 {
-       return le32_to_cpup((__le32*)&tx_resp->status +
+       return le32_to_cpup((__le32 *)&tx_resp->status +
                            tx_resp->frame_count) & MAX_SN;
 }
 
@@ -1444,6 +1460,44 @@ static void iwl5000_temperature(struct iwl_priv *priv)
        priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
 }
 
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwl5000_calc_rssi(struct iwl_priv *priv,
+                            struct iwl_rx_phy_res *rx_resp)
+{
+       /* data from PHY/DSP regarding signal strength, etc.,
+        *   contents are always there, not configurable by host
+        */
+       struct iwl5000_non_cfg_phy *ncphy =
+               (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+       u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
+       u8 agc;
+
+       val  = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]);
+       agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS;
+
+       /* Find max rssi among 3 possible receivers.
+        * These values are measured by the digital signal processor (DSP).
+        * They should stay fairly constant even as the signal strength varies,
+        *   if the radio's automatic gain control (AGC) is working right.
+        * AGC value (see below) will provide the "interesting" info.
+        */
+       val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]);
+       rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS;
+       rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS;
+       val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]);
+       rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS;
+
+       max_rssi = max_t(u32, rssi_a, rssi_b);
+       max_rssi = max_t(u32, max_rssi, rssi_c);
+
+       IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+               rssi_a, rssi_b, rssi_c, max_rssi, agc);
+
+       /* dBm = max_rssi dB - agc dB - constant.
+        * Higher AGC (higher radio gain) means lower signal. */
+       return max_rssi - agc - IWL_RSSI_OFFSET;
+}
+
 static struct iwl_hcmd_ops iwl5000_hcmd = {
        .rxon_assoc = iwl5000_send_rxon_assoc,
 };
@@ -1454,6 +1508,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
        .gain_computation = iwl5000_gain_computation,
        .chain_noise_reset = iwl5000_chain_noise_reset,
        .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
+       .calc_rssi = iwl5000_calc_rssi,
 };
 
 static struct iwl_lib_ops iwl5000_lib = {