Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl-4965.c
index bd856df..b07874f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 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
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -1203,7 +1204,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
        iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
 
        /* calculate tx gain adjustment based on power supply voltage */
-       voltage = priv->calib_info->voltage;
+       voltage = le16_to_cpu(priv->calib_info->voltage);
        init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
        voltage_compensation =
            iwl4965_get_voltage_compensation(voltage, init_voltage);
@@ -1433,14 +1434,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
        return ret;
 }
 
-#ifdef IEEE80211_CONF_CHANNEL_SWITCH
 static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 {
        int rc;
        u8 band = 0;
        bool is_ht40 = false;
        u8 ctrl_chan_high = 0;
-       struct iwl4965_channel_switch_cmd cmd = { 0 };
+       struct iwl4965_channel_switch_cmd cmd;
        const struct iwl_channel_info *ch_info;
 
        band = priv->band == IEEE80211_BAND_2GHZ;
@@ -1450,19 +1450,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
        is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
 
        if (is_ht40 &&
-           (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+           (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
                ctrl_chan_high = 1;
 
        cmd.band = band;
        cmd.expect_beacon = 0;
        cmd.channel = cpu_to_le16(channel);
-       cmd.rxon_flags = priv->active_rxon.flags;
-       cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
+       cmd.rxon_flags = priv->staging_rxon.flags;
+       cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
        cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
        if (ch_info)
                cmd.expect_beacon = is_channel_radar(ch_info);
-       else
-               cmd.expect_beacon = 1;
+       else {
+               IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+                       priv->active_rxon.channel, channel);
+               return -EFAULT;
+       }
 
        rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
                                      ctrl_chan_high, &cmd.tx_power);
@@ -1471,10 +1474,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
                return rc;
        }
 
-       rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-       return rc;
+       priv->switch_rxon.channel = cpu_to_le16(channel);
+       priv->switch_rxon.switch_in_progress = true;
+
+       return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
 }
-#endif
 
 /**
  * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
@@ -1814,8 +1818,9 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
        addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
        addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
        addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+       addsta->sleep_tx_count = cmd->sleep_tx_count;
        addsta->reserved1 = cpu_to_le16(0);
-       addsta->reserved2 = cpu_to_le32(0);
+       addsta->reserved2 = cpu_to_le16(0);
 
        return (u16)sizeof(struct iwl4965_addsta_cmd);
 }
@@ -1861,8 +1866,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
                info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
                info->status.rates[0].count = tx_resp->failure_frame + 1;
                info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-               info->flags |= iwl_is_tx_success(status) ?
-                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
                /* FIXME: code repetition end */
 
@@ -1957,7 +1961,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
        struct ieee80211_tx_info *info;
        struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        u32  status = le32_to_cpu(tx_resp->u.status);
-       int tid = MAX_TID_COUNT;
+       int uninitialized_var(tid);
        int sta_id;
        int freed;
        u8 *qc = NULL;
@@ -2004,7 +2008,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                        IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
                                           "%d index %d\n", scd_ssn , index);
                        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) &&
@@ -2017,8 +2021,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                }
        } else {
                info->status.rates[0].count = tx_resp->failure_frame + 1;
-               info->flags |= iwl_is_tx_success(status) ?
-                                       IEEE80211_TX_STAT_ACK : 0;
+               info->flags |= iwl_tx_status_to_mac80211(status);
                iwl_hwrate_to_tx_control(priv,
                                        le32_to_cpu(tx_resp->rate_n_flags),
                                        info);
@@ -2171,6 +2174,7 @@ static struct iwl_lib_ops iwl4965_lib = {
        .load_ucode = iwl4965_load_bsm,
        .dump_nic_event_log = iwl_dump_nic_event_log,
        .dump_nic_error_log = iwl_dump_nic_error_log,
+       .set_channel_switch = iwl4965_hw_channel_switch,
        .apm_ops = {
                .init = iwl_apm_init,
                .stop = iwl_apm_stop,
@@ -2202,9 +2206,10 @@ static struct iwl_lib_ops iwl4965_lib = {
                .temperature = iwl4965_temperature_calib,
                .set_ct_kill = iwl4965_set_ct_threshold,
        },
+       .add_bcast_station = iwl_add_bcast_station,
 };
 
-static struct iwl_ops iwl4965_ops = {
+static const struct iwl_ops iwl4965_ops = {
        .ucode = &iwl4965_ucode,
        .lib = &iwl4965_lib,
        .hcmd = &iwl4965_hcmd,
@@ -2226,7 +2231,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
        .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
        .mod_params = &iwl4965_mod_params,
        .valid_tx_ant = ANT_AB,
-       .valid_rx_ant = ANT_AB,
+       .valid_rx_ant = ANT_ABC,
        .pll_cfg_val = 0,
        .set_l0s = true,
        .use_bsm = true,
@@ -2235,6 +2240,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
        .broken_powersave = true,
        .led_compensation = 61,
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 };
 
 /* Module firmware */