Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-5000.c
index de45f30..e476acb 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -179,14 +179,24 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
                        data->delta_gain_code[i] = 0;
                        continue;
                }
-               delta_g = (1000 * ((s32)average_noise[default_chain] -
+
+               delta_g = (priv->cfg->chain_noise_scale *
+                       ((s32)average_noise[default_chain] -
                        (s32)average_noise[i])) / 1500;
+
                /* bound gain by 2 bits value max, 3rd bit is sign */
                data->delta_gain_code[i] =
                        min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
 
                if (delta_g < 0)
-                       /* set negative sign */
+                       /*
+                        * set negative sign ...
+                        * note to Intel developers:  This is uCode API format,
+                        *   not the format of any internal device registers.
+                        *   Do not change this format for e.g. 6050 or similar
+                        *   devices.  Change format only if more resolution
+                        *   (i.e. more than 2 bits magnitude) is needed.
+                        */
                        data->delta_gain_code[i] |= (1 << 2);
        }
 
@@ -263,8 +273,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
 
        .auto_corr_max_ofdm = 120,
        .auto_corr_max_ofdm_mrc = 210,
-       .auto_corr_max_ofdm_x1 = 155,
-       .auto_corr_max_ofdm_mrc_x1 = 290,
+       .auto_corr_max_ofdm_x1 = 120,
+       .auto_corr_max_ofdm_mrc_x1 = 240,
 
        .auto_corr_min_cck = 125,
        .auto_corr_max_cck = 200,
@@ -412,12 +422,14 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
 /*
  * ucode
  */
-static int iwl5000_load_section(struct iwl_priv *priv,
-                               struct fw_desc *image,
-                               u32 dst_addr)
+static int iwl5000_load_section(struct iwl_priv *priv, const char *name,
+                               struct fw_desc *image, u32 dst_addr)
 {
        dma_addr_t phy_addr = image->p_addr;
        u32 byte_cnt = image->len;
+       int ret;
+
+       priv->ucode_write_complete = 0;
 
        iwl_write_direct32(priv,
                FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
@@ -447,57 +459,36 @@ static int iwl5000_load_section(struct iwl_priv *priv,
                FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE    |
                FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-       return 0;
-}
-
-static int iwl5000_load_given_ucode(struct iwl_priv *priv,
-               struct fw_desc *inst_image,
-               struct fw_desc *data_image)
-{
-       int ret = 0;
-
-       ret = iwl5000_load_section(priv, inst_image,
-                                  IWL50_RTC_INST_LOWER_BOUND);
-       if (ret)
-               return ret;
-
-       IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n");
+       IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
                                        priv->ucode_write_complete, 5 * HZ);
        if (ret == -ERESTARTSYS) {
-               IWL_ERR(priv, "Could not load the INST uCode section due "
-                       "to interrupt\n");
+               IWL_ERR(priv, "Could not load the %s uCode section due "
+                       "to interrupt\n", name);
                return ret;
        }
        if (!ret) {
-               IWL_ERR(priv, "Could not load the INST uCode section\n");
+               IWL_ERR(priv, "Could not load the %s uCode section\n",
+                       name);
                return -ETIMEDOUT;
        }
 
-       priv->ucode_write_complete = 0;
-
-       ret = iwl5000_load_section(
-               priv, data_image, IWL50_RTC_DATA_LOWER_BOUND);
-       if (ret)
-               return ret;
+       return 0;
+}
 
-       IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n");
+static int iwl5000_load_given_ucode(struct iwl_priv *priv,
+               struct fw_desc *inst_image,
+               struct fw_desc *data_image)
+{
+       int ret = 0;
 
-       ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-                               priv->ucode_write_complete, 5 * HZ);
-       if (ret == -ERESTARTSYS) {
-               IWL_ERR(priv, "Could not load the INST uCode section due "
-                       "to interrupt\n");
+       ret = iwl5000_load_section(priv, "INST", inst_image,
+                                  IWL50_RTC_INST_LOWER_BOUND);
+       if (ret)
                return ret;
-       } else if (!ret) {
-               IWL_ERR(priv, "Could not load the DATA uCode section\n");
-               return -ETIMEDOUT;
-       } else
-               ret = 0;
 
-       priv->ucode_write_complete = 0;
-
-       return ret;
+       return iwl5000_load_section(priv, "DATA", data_image,
+                                   IWL50_RTC_DATA_LOWER_BOUND);
 }
 
 int iwl5000_load_ucode(struct iwl_priv *priv)
@@ -657,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
 
        iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
 
+       /* make sure all queue are not stopped */
+       memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+       for (i = 0; i < 4; i++)
+               atomic_set(&priv->queue_stop_count[i], 0);
+
+       /* reset to 0 to enable all the queue first */
+       priv->txq_ctx_active_msk = 0;
        /* map qos queues to fifos one-to-one */
        for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
                int ac = iwl5000_default_queue_to_tx_fifo[i];
@@ -781,7 +779,7 @@ void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
 
        scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
 
-       if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+       if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
                scd_bc_tbl[txq_id].
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
@@ -800,12 +798,12 @@ void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
        if (txq_id != IWL_CMD_QUEUE_NUM)
                sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
 
-       bc_ent =  cpu_to_le16(1 | (sta_id << 12));
+       bc_ent = cpu_to_le16(1 | (sta_id << 12));
        scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
 
-       if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+       if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
                scd_bc_tbl[txq_id].
-                       tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =  bc_ent;
+                       tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
 }
 
 static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
@@ -1125,7 +1123,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
                                        scd_ssn , index, txq_id, txq->swq_id);
 
                        freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-                       priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+                       iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
                        if (priv->mac80211_registered &&
                            (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
@@ -1153,16 +1151,14 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
                                   tx_resp->failure_frame);
 
                freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-               if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
-                       priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+               iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
                if (priv->mac80211_registered &&
                    (iwl_queue_space(&txq->q) > txq->q.low_mark))
                        iwl_wake_queue(priv, txq_id);
        }
 
-       if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
-               iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+       iwl_txq_check_empty(priv, sta_id, tid, txq_id);
 
        if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
                IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
@@ -1466,6 +1462,8 @@ struct iwl_lib_ops iwl5000_lib = {
        .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
        .dump_nic_event_log = iwl_dump_nic_event_log,
        .dump_nic_error_log = iwl_dump_nic_error_log,
+       .dump_csr = iwl_dump_csr,
+       .dump_fh = iwl_dump_fh,
        .load_ucode = iwl5000_load_ucode,
        .init_alive_start = iwl5000_init_alive_start,
        .alive_notify = iwl5000_alive_notify,
@@ -1501,6 +1499,7 @@ struct iwl_lib_ops iwl5000_lib = {
                .temperature = iwl5000_temperature,
                .set_ct_kill = iwl5000_set_ct_threshold,
         },
+       .add_bcast_station = iwl_add_bcast_station,
 };
 
 static struct iwl_lib_ops iwl5150_lib = {
@@ -1518,6 +1517,7 @@ static struct iwl_lib_ops iwl5150_lib = {
        .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
        .dump_nic_event_log = iwl_dump_nic_event_log,
        .dump_nic_error_log = iwl_dump_nic_error_log,
+       .dump_csr = iwl_dump_csr,
        .load_ucode = iwl5000_load_ucode,
        .init_alive_start = iwl5000_init_alive_start,
        .alive_notify = iwl5000_alive_notify,
@@ -1553,9 +1553,10 @@ static struct iwl_lib_ops iwl5150_lib = {
                .temperature = iwl5150_temperature,
                .set_ct_kill = iwl5150_set_ct_threshold,
         },
+       .add_bcast_station = iwl_add_bcast_station,
 };
 
-static struct iwl_ops iwl5000_ops = {
+static const struct iwl_ops iwl5000_ops = {
        .ucode = &iwl5000_ucode,
        .lib = &iwl5000_lib,
        .hcmd = &iwl5000_hcmd,
@@ -1563,7 +1564,7 @@ static struct iwl_ops iwl5000_ops = {
        .led = &iwlagn_led_ops,
 };
 
-static struct iwl_ops iwl5150_ops = {
+static const struct iwl_ops iwl5150_ops = {
        .ucode = &iwl5000_ucode,
        .lib = &iwl5150_lib,
        .hcmd = &iwl5000_hcmd,
@@ -1600,7 +1601,8 @@ struct iwl_cfg iwl5300_agn_cfg = {
        .led_compensation = 51,
        .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5100_bgn_cfg = {
@@ -1625,6 +1627,8 @@ struct iwl_cfg iwl5100_bgn_cfg = {
        .led_compensation = 51,
        .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5100_abg_cfg = {
@@ -1647,6 +1651,8 @@ struct iwl_cfg iwl5100_abg_cfg = {
        .use_bsm = false,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
@@ -1671,7 +1677,8 @@ struct iwl_cfg iwl5100_agn_cfg = {
        .led_compensation = 51,
        .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5350_agn_cfg = {
@@ -1696,7 +1703,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
        .led_compensation = 51,
        .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5150_agn_cfg = {
@@ -1721,7 +1729,8 @@ struct iwl_cfg iwl5150_agn_cfg = {
        .led_compensation = 51,
        .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-       .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 struct iwl_cfg iwl5150_abg_cfg = {
@@ -1744,6 +1753,8 @@ struct iwl_cfg iwl5150_abg_cfg = {
        .use_bsm = false,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+       .chain_noise_scale = 1000,
 };
 
 MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));