iwlwifi: prepare for PAN queue/fifo assignment
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-4965.c
index d3afddae8d9f18d6f308bb79189ed5deb5921d39..cda389c3b0259c972a76f3b40f0dcb16962940ae 100644 (file)
@@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
 {
        struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
 
-       if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
+       if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+           iwl_is_any_associated(priv)) {
                struct iwl_calib_diff_gain_cmd cmd;
 
+               /* clear data for chain noise calibration algorithm */
+               data->chain_noise_a = 0;
+               data->chain_noise_b = 0;
+               data->chain_noise_c = 0;
+               data->chain_signal_a = 0;
+               data->chain_signal_b = 0;
+               data->chain_signal_c = 0;
+               data->beacon_count = 0;
+
                memset(&cmd, 0, sizeof(cmd));
                cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
                cmd.diff_gain_a = 0;
@@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
                /* Mark so we run this algo only once! */
                data->state = IWL_CHAIN_NOISE_CALIBRATED;
        }
-       data->chain_noise_a = 0;
-       data->chain_noise_b = 0;
-       data->chain_noise_c = 0;
-       data->chain_signal_a = 0;
-       data->chain_signal_b = 0;
-       data->chain_signal_c = 0;
-       data->beacon_count = 0;
 }
 
 static void iwl4965_bg_txpower_work(struct work_struct *work)
@@ -573,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
        /* Activate all Tx DMA/FIFO channels */
        priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
 
-       iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+       iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
 
        /* make sure all queue are not stopped */
        memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -584,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
        priv->txq_ctx_active_msk = 0;
        /* Map each Tx/cmd queue to its corresponding fifo */
        BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
+
        for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
                int ac = default_queue_to_tx_fifo[i];
 
@@ -669,6 +673,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
                priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
 
        priv->hw_params.sens = &iwl4965_sensitivity;
+       priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
 
        return 0;
 }
@@ -1370,6 +1375,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
        u8 band = 0;
        bool is_ht40 = false;
        u8 ctrl_chan_high = 0;
+       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
        if (test_bit(STATUS_SCANNING, &priv->status)) {
                /* If this gets hit a lot, switch it to a BUG() and catch
@@ -1381,17 +1387,16 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
 
        band = priv->band == IEEE80211_BAND_2GHZ;
 
-       is_ht40 =  is_ht40_channel(priv->active_rxon.flags);
+       is_ht40 = is_ht40_channel(ctx->active.flags);
 
-       if (is_ht40 &&
-           (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+       if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
                ctrl_chan_high = 1;
 
        cmd.band = band;
-       cmd.channel = priv->active_rxon.channel;
+       cmd.channel = ctx->active.channel;
 
        ret = iwl4965_fill_txpower_tbl(priv, band,
-                               le16_to_cpu(priv->active_rxon.channel),
+                               le16_to_cpu(ctx->active.channel),
                                is_ht40, ctrl_chan_high, &cmd.tx_power);
        if (ret)
                goto out;
@@ -1402,12 +1407,13 @@ out:
        return ret;
 }
 
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
+                                  struct iwl_rxon_context *ctx)
 {
        int ret = 0;
        struct iwl4965_rxon_assoc_cmd rxon_assoc;
-       const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-       const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+       const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
+       const struct iwl_rxon_cmd *rxon2 = &ctx->active;
 
        if ((rxon1->flags == rxon2->flags) &&
            (rxon1->filter_flags == rxon2->filter_flags) &&
@@ -1422,16 +1428,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
                return 0;
        }
 
-       rxon_assoc.flags = priv->staging_rxon.flags;
-       rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-       rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-       rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+       rxon_assoc.flags = ctx->staging.flags;
+       rxon_assoc.filter_flags = ctx->staging.filter_flags;
+       rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+       rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
        rxon_assoc.reserved = 0;
        rxon_assoc.ofdm_ht_single_stream_basic_rates =
-           priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+           ctx->staging.ofdm_ht_single_stream_basic_rates;
        rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-           priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-       rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+           ctx->staging.ofdm_ht_dual_stream_basic_rates;
+       rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
 
        ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
                                     sizeof(rxon_assoc), &rxon_assoc, NULL);
@@ -1441,47 +1447,82 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
        return ret;
 }
 
-static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
+                                    struct ieee80211_channel_switch *ch_switch)
 {
+       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        int rc;
        u8 band = 0;
        bool is_ht40 = false;
        u8 ctrl_chan_high = 0;
        struct iwl4965_channel_switch_cmd cmd;
        const struct iwl_channel_info *ch_info;
-
+       u32 switch_time_in_usec, ucode_switch_time;
+       u16 ch;
+       u32 tsf_low;
+       u8 switch_count;
+       u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+       struct ieee80211_vif *vif = priv->vif;
        band = priv->band == IEEE80211_BAND_2GHZ;
 
-       ch_info = iwl_get_channel_info(priv, priv->band, channel);
-
-       is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
+       is_ht40 = is_ht40_channel(ctx->staging.flags);
 
        if (is_ht40 &&
-           (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+           (ctx->staging.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->staging_rxon.flags;
-       cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
-       cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+       ch = ch_switch->channel->hw_value;
+       cmd.channel = cpu_to_le16(ch);
+       cmd.rxon_flags = ctx->staging.flags;
+       cmd.rxon_filter_flags = ctx->staging.filter_flags;
+       switch_count = ch_switch->count;
+       tsf_low = ch_switch->timestamp & 0x0ffffffff;
+       /*
+        * calculate the ucode channel switch time
+        * adding TSF as one of the factor for when to switch
+        */
+       if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+               if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+                   beacon_interval)) {
+                       switch_count -= (priv->ucode_beacon_time -
+                               tsf_low) / beacon_interval;
+               } else
+                       switch_count = 0;
+       }
+       if (switch_count <= 1)
+               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+       else {
+               switch_time_in_usec =
+                       vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+               ucode_switch_time = iwl_usecs_to_beacons(priv,
+                                                        switch_time_in_usec,
+                                                        beacon_interval);
+               cmd.switch_time = iwl_add_beacon_time(priv,
+                                                     priv->ucode_beacon_time,
+                                                     ucode_switch_time,
+                                                     beacon_interval);
+       }
+       IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+                     cmd.switch_time);
+       ch_info = iwl_get_channel_info(priv, priv->band, ch);
        if (ch_info)
                cmd.expect_beacon = is_channel_radar(ch_info);
        else {
                IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-                       priv->active_rxon.channel, channel);
+                       ctx->active.channel, ch);
                return -EFAULT;
        }
 
-       rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
+       rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
                                      ctrl_chan_high, &cmd.tx_power);
        if (rc) {
                IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
                return rc;
        }
 
-       priv->switch_rxon.channel = cpu_to_le16(channel);
+       priv->switch_rxon.channel = cmd.channel;
        priv->switch_rxon.switch_in_progress = true;
 
        return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
@@ -1542,7 +1583,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
        u32 R4;
 
        if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-               (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+           (priv->_agn.statistics.flag &
+                       STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
                IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
                R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
                R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@@ -1566,8 +1608,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
        if (!test_bit(STATUS_TEMPERATURE, &priv->status))
                vt = sign_extend(R4, 23);
        else
-               vt = sign_extend(
-                       le32_to_cpu(priv->statistics.general.temperature), 23);
+               vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
+                                general.common.temperature), 23);
 
        IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 
@@ -1747,6 +1789,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 {
        unsigned long flags;
        u16 ra_tid;
+       int ret;
 
        if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1762,7 +1805,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
        ra_tid = BUILD_RAxTID(sta_id, tid);
 
        /* Modify device's station table to Tx this TID */
-       iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+       ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+       if (ret)
+               return ret;
 
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -1870,7 +1915,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
                IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
                                   agg->frame_count, agg->start_idx, idx);
 
-               info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
+               info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
                info->status.rates[0].count = tx_resp->failure_frame + 1;
                info->flags &= ~IEEE80211_TX_CTL_AMPDU;
                info->flags |= iwl_tx_status_to_mac80211(status);
@@ -2026,6 +2071,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
        int sta_id;
        int freed;
        u8 *qc = NULL;
+       unsigned long flags;
 
        if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
                IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
@@ -2035,7 +2081,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                return;
        }
 
-       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
+       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
        memset(&info->status, 0, sizeof(info->status));
 
        hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
@@ -2050,10 +2096,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                return;
        }
 
+       spin_lock_irqsave(&priv->sta_lock, flags);
        if (txq->sched_retry) {
                const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
                struct iwl_ht_agg *agg = NULL;
-
                WARN_ON(!qc);
 
                agg = &priv->stations[sta_id].tid[tid].agg;
@@ -2110,6 +2156,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
                iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
 
        iwl_check_abort_status(priv, tx_resp->frame_count, status);
+
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 
 static int iwl4965_calc_rssi(struct iwl_priv *priv,
@@ -2178,7 +2226,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
        .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
        .chain_noise_reset = iwl4965_chain_noise_reset,
        .gain_computation = iwl4965_gain_computation,
-       .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+       .tx_cmd_protection = iwlcore_tx_cmd_protection,
        .calc_rssi = iwl4965_calc_rssi,
        .request_scan = iwlagn_request_scan,
 };
@@ -2235,11 +2283,14 @@ static struct iwl_lib_ops iwl4965_lib = {
                .set_ct_kill = iwl4965_set_ct_threshold,
        },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
+               .bt_stats_read = iwl_ucode_bt_stats_read,
        },
+       .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
 };
 
@@ -2274,7 +2325,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
        .led_compensation = 61,
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .temperature_kelvin = true,
        .max_event_log_size = 512,
        .tx_power_by_driver = true,
@@ -2285,7 +2336,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
         * Force use of chains B and C for scan RX on 5 GHz band
         * because the device has off-channel reception on chain A.
         */
-       .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
+       .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
 };
 
 /* Module firmware */
This page took 0.031838 seconds and 5 git commands to generate.