summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c42
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ict.c305
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c110
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h74
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c418
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c82
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h90
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c115
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c78
24 files changed, 687 insertions, 789 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 4e378faee65..e31a5ccebea 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -9,7 +9,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
# AGN
obj-$(CONFIG_IWLAGN) += iwlagn.o
-iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
+iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 3bf2e6e9b2d..59b092eaa82 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -42,6 +42,7 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-sta.h"
+#include "iwl-agn.h"
#include "iwl-helpers.h"
#include "iwl-5000-hw.h"
#include "iwl-agn-led.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 3a876a8ece3..074f42a7dca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -78,6 +78,8 @@
/* RSSI to dBm */
#define IWL39_RSSI_OFFSET 95
+#define IWL_DEFAULT_TX_POWER 0x0F
+
/*
* EEPROM related constants, enums, and structures.
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 47909f94271..b588cb69536 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -372,11 +372,11 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
}
}
- priv->sta_supp_rates = sta->supp_rates[sband->band];
+ priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (sband->band == IEEE80211_BAND_5GHZ) {
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
- priv->sta_supp_rates = priv->sta_supp_rates <<
+ priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
IWL_FIRST_OFDM_RATE;
}
@@ -946,7 +946,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
spin_unlock_irqrestore(&rs_sta->lock, flags);
- rssi = priv->last_rx_rssi;
+ rssi = priv->_3945.last_rx_rssi;
if (rssi == 0)
rssi = IWL_MIN_RSSI_VAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e0678d92105..12a42fc743d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -242,7 +242,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
next_rate = IWL_RATE_6M_INDEX;
break;
case IEEE80211_BAND_2GHZ:
- if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+ if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
iwl_is_associated(priv)) {
if (rate == IWL_RATE_11M_INDEX)
next_rate = IWL_RATE_5M_INDEX;
@@ -359,7 +359,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
(int)sizeof(struct iwl3945_notif_statistics),
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
- memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
+ memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
}
/******************************************************************************
@@ -705,9 +705,10 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
if (network_packet) {
- priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
- priv->last_tsf = le64_to_cpu(rx_end->timestamp);
- priv->last_rx_rssi = rx_status.signal;
+ priv->_3945.last_beacon_time =
+ le32_to_cpu(rx_end->beacon_timestamp);
+ priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
+ priv->_3945.last_rx_rssi = rx_status.signal;
priv->last_rx_noise = rx_status.noise;
}
@@ -956,7 +957,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
iwl_write_direct32(priv, FH39_TSSR_CBB_BASE,
- priv->shared_phys);
+ priv->_3945.shared_phys);
iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
@@ -1606,7 +1607,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
int power;
/* Get this chnlgrp's rate-to-max/clip-powers table */
- clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
+ clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
/* Get this channel's rate-to-current-power settings table */
power_info = ch_info->power_info;
@@ -1732,7 +1733,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
}
/* Get this chnlgrp's rate-to-max/clip-powers table */
- clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
+ clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
for (scan_tbl_index = 0;
@@ -1997,13 +1998,13 @@ void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
reschedule:
queue_delayed_work(priv->workqueue,
- &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ);
+ &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
}
static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
- thermal_periodic.work);
+ _3945.thermal_periodic.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -2139,7 +2140,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
* power peaks, without too much distortion (clipping).
*/
/* we'll fill in this array with h/w max power levels */
- clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers;
+ clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
/* divide factory saturation power by 2 to find -3dB level */
satur_pwr = (s8) (group->saturation_power >> 1);
@@ -2223,7 +2224,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
/* Get this chnlgrp's rate->max/clip-powers table */
- clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers;
+ clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
/* calculate power index *adjustment* value according to
* diff between current temperature and factory temperature */
@@ -2331,7 +2332,7 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
int txq_id = txq->q.id;
- struct iwl3945_shared *shared_data = priv->shared_virt;
+ struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
@@ -2431,7 +2432,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
- if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+ if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
iwl_is_associated(priv)) {
index = IWL_FIRST_CCK_RATE;
@@ -2470,10 +2471,11 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
memset((void *)&priv->hw_params, 0,
sizeof(struct iwl_hw_params));
- priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
- sizeof(struct iwl3945_shared),
- &priv->shared_phys, GFP_KERNEL);
- if (!priv->shared_virt) {
+ priv->_3945.shared_virt =
+ dma_alloc_coherent(&priv->pci_dev->dev,
+ sizeof(struct iwl3945_shared),
+ &priv->_3945.shared_phys, GFP_KERNEL);
+ if (!priv->_3945.shared_virt) {
IWL_ERR(priv, "failed to allocate pci memory\n");
mutex_unlock(&priv->mutex);
return -ENOMEM;
@@ -2536,13 +2538,13 @@ void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
{
- INIT_DELAYED_WORK(&priv->thermal_periodic,
+ INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
iwl3945_bg_reg_txpower_periodic);
}
void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
{
- cancel_delayed_work(&priv->thermal_periodic);
+ cancel_delayed_work(&priv->_3945.thermal_periodic);
}
/* check contents of special bootstrap uCode SRAM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 1bd2cd83602..644aacfbd7d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -502,14 +502,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}
-static const u16 default_queue_to_tx_fifo[] = {
- IWL_TX_FIFO_AC3,
- IWL_TX_FIFO_AC2,
- IWL_TX_FIFO_AC1,
- IWL_TX_FIFO_AC0,
+static const s8 default_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
IWL49_CMD_FIFO_NUM,
- IWL_TX_FIFO_HCCA_1,
- IWL_TX_FIFO_HCCA_2
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
};
static int iwl4965_alive_notify(struct iwl_priv *priv)
@@ -589,9 +589,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */
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];
+
iwl_txq_ctx_activate(priv, i);
+
+ if (ac == IWL_TX_FIFO_UNUSED)
+ continue;
+
iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e476acb53aa..37e1e77f513 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -43,6 +43,7 @@
#include "iwl-io.h"
#include "iwl-sta.h"
#include "iwl-helpers.h"
+#include "iwl-agn.h"
#include "iwl-agn-led.h"
#include "iwl-5000-hw.h"
#include "iwl-6000-hw.h"
@@ -63,14 +64,17 @@
#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
-static const u16 iwl5000_default_queue_to_tx_fifo[] = {
- IWL_TX_FIFO_AC3,
- IWL_TX_FIFO_AC2,
- IWL_TX_FIFO_AC1,
- IWL_TX_FIFO_AC0,
+static const s8 iwl5000_default_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
IWL50_CMD_FIFO_NUM,
- IWL_TX_FIFO_HCCA_1,
- IWL_TX_FIFO_HCCA_2
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
};
/* NIC configuration for 5000 series */
@@ -579,9 +583,9 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
txq->sched_retry = scd_retry;
- IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
+ IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
active ? "Activate" : "Deactivate",
- scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
+ scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
}
int iwl5000_alive_notify(struct iwl_priv *priv)
@@ -656,25 +660,21 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* map qos queues to fifos one-to-one */
+ BUILD_BUG_ON(ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo) != 10);
+
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
int ac = iwl5000_default_queue_to_tx_fifo[i];
+
iwl_txq_ctx_activate(priv, i);
+
+ if (ac == IWL_TX_FIFO_UNUSED)
+ continue;
+
iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
}
- /*
- * TODO - need to initialize these queues and map them to FIFOs
- * in the loop above, not only mark them as active. We do this
- * because we want the first aggregation queue to be queue #10,
- * but do not use 8 or 9 otherwise yet.
- */
- iwl_txq_ctx_activate(priv, 7);
- iwl_txq_ctx_activate(priv, 8);
- iwl_txq_ctx_activate(priv, 9);
-
spin_unlock_irqrestore(&priv->lock, flags);
-
iwl_send_wimax_coex(priv);
iwl5000_set_Xtal_calib(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index c4844adff92..4b7bc008220 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -42,6 +42,7 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-sta.h"
+#include "iwl-agn.h"
#include "iwl-helpers.h"
#include "iwl-5000-hw.h"
#include "iwl-6000-hw.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
new file mode 100644
index 00000000000..4c5395eae95
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
@@ -0,0 +1,305 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-agn.h"
+#include "iwl-helpers.h"
+
+#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* Free dram table */
+void iwl_free_isr_ict(struct iwl_priv *priv)
+{
+ if (priv->_agn.ict_tbl_vir) {
+ dma_free_coherent(&priv->pci_dev->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ priv->_agn.ict_tbl_vir,
+ priv->_agn.ict_tbl_dma);
+ priv->_agn.ict_tbl_vir = NULL;
+ }
+}
+
+
+/* allocate dram shared table it is a PAGE_SIZE aligned
+ * also reset all data related to ICT table interrupt.
+ */
+int iwl_alloc_isr_ict(struct iwl_priv *priv)
+{
+
+ if (priv->cfg->use_isr_legacy)
+ return 0;
+ /* allocate shrared data table */
+ priv->_agn.ict_tbl_vir =
+ dma_alloc_coherent(&priv->pci_dev->dev,
+ (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+ &priv->_agn.ict_tbl_dma, GFP_KERNEL);
+ if (!priv->_agn.ict_tbl_vir)
+ return -ENOMEM;
+
+ /* align table to PAGE_SIZE boundry */
+ priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE);
+
+ IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
+ (unsigned long long)priv->_agn.ict_tbl_dma,
+ (unsigned long long)priv->_agn.aligned_ict_tbl_dma,
+ (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
+
+ priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir +
+ (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma);
+
+ IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
+ priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir,
+ (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
+
+ /* reset table and index to all 0 */
+ memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+ priv->_agn.ict_index = 0;
+
+ /* add periodic RX interrupt */
+ priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
+ return 0;
+}
+
+/* Device is going up inform it about using ICT interrupt table,
+ * also we need to tell the driver to start using ICT interrupt.
+ */
+int iwl_reset_ict(struct iwl_priv *priv)
+{
+ u32 val;
+ unsigned long flags;
+
+ if (!priv->_agn.ict_tbl_vir)
+ return 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl_disable_interrupts(priv);
+
+ memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+
+ val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT;
+
+ val |= CSR_DRAM_INT_TBL_ENABLE;
+ val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
+
+ IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
+ "aligned dma address %Lx\n",
+ val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma);
+
+ iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
+ priv->_agn.use_ict = true;
+ priv->_agn.ict_index = 0;
+ iwl_write32(priv, CSR_INT, priv->inta_mask);
+ iwl_enable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+/* Device is going down disable ict interrupt usage */
+void iwl_disable_ict(struct iwl_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->_agn.use_ict = false;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static irqreturn_t iwl_isr(int irq, void *data)
+{
+ struct iwl_priv *priv = data;
+ u32 inta, inta_mask;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ u32 inta_fh;
+#endif
+ if (!priv)
+ return IRQ_NONE;
+
+ spin_lock(&priv->lock);
+
+ /* Disable (but don't clear!) interrupts here to avoid
+ * back-to-back ISRs and sporadic interrupts from our NIC.
+ * If we have something to service, the tasklet will re-enable ints.
+ * If we *don't* have something, we'll re-enable before leaving here. */
+ inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+ /* Discover which interrupts are active/pending */
+ inta = iwl_read32(priv, CSR_INT);
+
+ /* Ignore interrupt if there's nothing in NIC to service.
+ * This may be due to IRQ shared with another device,
+ * or due to sporadic interrupts thrown from our NIC. */
+ if (!inta) {
+ IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+ goto none;
+ }
+
+ if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+ /* Hardware disappeared. It might have already raised
+ * an interrupt */
+ IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+ goto unplugged;
+ }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
+ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
+ "fh 0x%08x\n", inta, inta_mask, inta_fh);
+ }
+#endif
+
+ priv->_agn.inta |= inta;
+ /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ if (likely(inta))
+ tasklet_schedule(&priv->irq_tasklet);
+ else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
+ iwl_enable_interrupts(priv);
+
+ unplugged:
+ spin_unlock(&priv->lock);
+ return IRQ_HANDLED;
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service. */
+ /* only Re-enable if diabled by irq and no schedules tasklet. */
+ if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
+ iwl_enable_interrupts(priv);
+
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+}
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+irqreturn_t iwl_isr_ict(int irq, void *data)
+{
+ struct iwl_priv *priv = data;
+ u32 inta, inta_mask;
+ u32 val = 0;
+
+ if (!priv)
+ return IRQ_NONE;
+
+ /* dram interrupt table not set yet,
+ * use legacy interrupt.
+ */
+ if (!priv->_agn.use_ict)
+ return iwl_isr(irq, data);
+
+ spin_lock(&priv->lock);
+
+ /* Disable (but don't clear!) interrupts here to avoid
+ * back-to-back ISRs and sporadic interrupts from our NIC.
+ * If we have something to service, the tasklet will re-enable ints.
+ * If we *don't* have something, we'll re-enable before leaving here.
+ */
+ inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+
+ /* Ignore interrupt if there's nothing in NIC to service.
+ * This may be due to IRQ shared with another device,
+ * or due to sporadic interrupts thrown from our NIC. */
+ if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) {
+ IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+ goto none;
+ }
+
+ /* read all entries that not 0 start with ict_index */
+ while (priv->_agn.ict_tbl[priv->_agn.ict_index]) {
+
+ val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]);
+ IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
+ priv->_agn.ict_index,
+ le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]));
+ priv->_agn.ict_tbl[priv->_agn.ict_index] = 0;
+ priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index,
+ ICT_COUNT);
+
+ }
+
+ /* We should not get this value, just ignore it. */
+ if (val == 0xffffffff)
+ val = 0;
+
+ /*
+ * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+ * (bit 15 before shifting it to 31) to clear when using interrupt
+ * coalescing. fortunately, bits 18 and 19 stay set when this happens
+ * so we use them to decide on the real state of the Rx bit.
+ * In order words, bit 15 is set if bit 18 or bit 19 are set.
+ */
+ if (val & 0xC0000)
+ val |= 0x8000;
+
+ inta = (0xff & val) | ((0xff00 & val) << 16);
+ IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
+ inta, inta_mask, val);
+
+ inta &= priv->inta_mask;
+ priv->_agn.inta |= inta;
+
+ /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ if (likely(inta))
+ tasklet_schedule(&priv->irq_tasklet);
+ else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) {
+ /* Allow interrupt if was disabled by this handler and
+ * no tasklet was schedules, We should not enable interrupt,
+ * tasklet will enable it.
+ */
+ iwl_enable_interrupts(priv);
+ }
+
+ spin_unlock(&priv->lock);
+ return IRQ_HANDLED;
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service.
+ * only Re-enable if disabled by irq.
+ */
+ if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
+ iwl_enable_interrupts(priv);
+
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 8bf7c20b9d3..84271cc62af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -597,10 +597,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
struct ieee80211_hdr *hdr,
enum iwl_table_type rate_type)
{
- if (hdr && is_multicast_ether_addr(hdr->addr1) &&
- lq_sta->active_rate_basic)
- return lq_sta->active_rate_basic;
-
if (is_legacy(rate_type)) {
return lq_sta->active_legacy_rate;
} else {
@@ -2552,7 +2548,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
- lq_sta->active_rate_basic = priv->active_rate_basic;
lq_sta->band = priv->band;
/*
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
@@ -2956,12 +2951,8 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
desc += sprintf(buff+desc,
"Bit Rate= %d Mb/s\n",
iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
- desc += sprintf(buff+desc,
- "Signal Level= %d dBm\tNoise Level= %d dBm\n",
- priv->last_rx_rssi, priv->last_rx_noise);
- desc += sprintf(buff+desc,
- "Tsf= 0x%llx\tBeacon time= 0x%08X\n",
- priv->last_tsf, priv->last_beacon_time);
+ desc += sprintf(buff+desc, "Noise Level= %d dBm\n",
+ priv->last_rx_noise);
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
return ret;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index e71923961e6..e182f5a0f73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -411,7 +411,6 @@ struct iwl_lq_sta {
u16 active_siso_rate;
u16 active_mimo2_rate;
u16 active_mimo3_rate;
- u16 active_rate_basic;
s8 max_rate_idx; /* Max rate set by user */
u8 missed_rate_counter;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 818367b57ba..efee4e39d28 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -54,6 +54,7 @@
#include "iwl-helpers.h"
#include "iwl-sta.h"
#include "iwl-calib.h"
+#include "iwl-agn.h"
/******************************************************************************
@@ -1258,9 +1259,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* Ack/clear/reset pending uCode interrupts.
* Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
*/
- iwl_write32(priv, CSR_INT, priv->inta);
+ iwl_write32(priv, CSR_INT, priv->_agn.inta);
- inta = priv->inta;
+ inta = priv->_agn.inta;
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
@@ -1273,8 +1274,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
- /* saved interrupt in inta variable now we can reset priv->inta */
- priv->inta = 0;
+ /* saved interrupt in inta variable now we can reset priv->_agn.inta */
+ priv->_agn.inta = 0;
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
@@ -2102,8 +2103,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
ieee80211_wake_queues(priv->hw);
- priv->active_rate = priv->rates_mask;
- priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
+ priv->active_rate = IWL_RATES_MASK;
/* Configure Tx antenna selection based on H/W config */
if (priv->cfg->ops->hcmd->set_tx_ant)
@@ -2144,18 +2144,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
iwl_power_update_mode(priv, true);
- /* reassociate for ADHOC mode */
- if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
- struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
- priv->vif);
- if (beacon)
- iwl_mac_beacon_update(priv->hw, beacon);
- }
-
-
- if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
- iwl_set_mode(priv, priv->iw_mode);
-
return;
restart:
@@ -2881,7 +2869,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100);
- mutex_unlock(&priv->mutex);
/* If we are getting WEP group key and we didn't receive any key mapping
* so far, we are in legacy wep mode (group key only), otherwise we are
@@ -2917,6 +2904,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = -EINVAL;
}
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -3121,87 +3109,6 @@ static ssize_t store_tx_power(struct device *d,
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-static ssize_t show_flags(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
-}
-
-static ssize_t store_flags(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- u32 flags;
- int ret = strict_strtoul(buf, 0, &val);
- if (ret)
- return ret;
- flags = (u32)val;
-
- mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
- /* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
- IWL_WARN(priv, "Could not cancel scan.\n");
- else {
- IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags);
- priv->staging_rxon.flags = cpu_to_le32(flags);
- iwlcore_commit_rxon(priv);
- }
- }
- mutex_unlock(&priv->mutex);
-
- return count;
-}
-
-static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
-
-static ssize_t show_filter_flags(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "0x%04X\n",
- le32_to_cpu(priv->active_rxon.filter_flags));
-}
-
-static ssize_t store_filter_flags(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- u32 filter_flags;
- int ret = strict_strtoul(buf, 0, &val);
- if (ret)
- return ret;
- filter_flags = (u32)val;
-
- mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
- /* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
- IWL_WARN(priv, "Could not cancel scan.\n");
- else {
- IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
- "0x%04X\n", filter_flags);
- priv->staging_rxon.filter_flags =
- cpu_to_le32(filter_flags);
- iwlcore_commit_rxon(priv);
- }
- }
- mutex_unlock(&priv->mutex);
-
- return count;
-}
-
-static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
- store_filter_flags);
-
-
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -3391,7 +3298,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
- priv->rates_mask = IWL_RATES_MASK;
/* Set the tx_power_user_lmt to the lowest power level
* this value will get overwritten by channel max power avg
* from eeprom */
@@ -3427,8 +3333,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
}
static struct attribute *iwl_sysfs_entries[] = {
- &dev_attr_flags.attr,
- &dev_attr_filter_flags.attr,
&dev_attr_statistics.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
new file mode 100644
index 00000000000..26eeb586ee0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_agn_h__
+#define __iwl_agn_h__
+
+#include "iwl-dev.h"
+
+int iwl_reset_ict(struct iwl_priv *priv);
+void iwl_disable_ict(struct iwl_priv *priv);
+int iwl_alloc_isr_ict(struct iwl_priv *priv);
+void iwl_free_isr_ict(struct iwl_priv *priv);
+irqreturn_t iwl_isr_ict(int irq, void *data);
+
+#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 112149e9b31..ec435e5491d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -114,8 +114,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
u32 iwl_debug_level;
EXPORT_SYMBOL(iwl_debug_level);
-static irqreturn_t iwl_isr(int irq, void *data);
-
/*
* Parameter order:
* rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
@@ -899,23 +897,10 @@ EXPORT_SYMBOL(iwl_full_rxon_required);
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
{
- int i;
- int rate_mask;
-
- /* Set rate mask*/
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
- rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
- else
- rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
-
- /* Find lowest valid rate */
- for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
- i = iwl_rates[i].next_ieee) {
- if (rate_mask & (1 << i))
- return iwl_rates[i].plcp;
- }
-
- /* No valid rate was found. Assign the lowest one */
+ /*
+ * Assign the lowest rate -- should really get this from
+ * the beacon skb from mac80211.
+ */
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
return IWL_RATE_1M_PLCP;
else
@@ -1240,14 +1225,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
if (!ch_info)
ch_info = &priv->channel_info[0];
- /*
- * in some case A channels are all non IBSS
- * in this case force B/G channel
- */
- if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
- !(is_channel_ibss(ch_info)))
- ch_info = &priv->channel_info[0];
-
priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
priv->band = ch_info->band;
@@ -1282,7 +1259,6 @@ static void iwl_set_rate(struct iwl_priv *priv)
}
priv->active_rate = 0;
- priv->active_rate_basic = 0;
for (i = 0; i < hw->n_bitrates; i++) {
rate = &(hw->bitrates[i]);
@@ -1290,30 +1266,13 @@ static void iwl_set_rate(struct iwl_priv *priv)
priv->active_rate |= (1 << rate->hw_value);
}
- IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n",
- priv->active_rate, priv->active_rate_basic);
+ IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
- /*
- * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK)
- * otherwise set it to the default of all CCK rates and 6, 12, 24 for
- * OFDM
- */
- if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK)
- priv->staging_rxon.cck_basic_rates =
- ((priv->active_rate_basic &
- IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF;
- else
- priv->staging_rxon.cck_basic_rates =
- (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
-
- if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK)
- priv->staging_rxon.ofdm_basic_rates =
- ((priv->active_rate_basic &
- (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >>
- IWL_FIRST_OFDM_RATE) & 0xFF;
- else
- priv->staging_rxon.ofdm_basic_rates =
- (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ priv->staging_rxon.cck_basic_rates =
+ (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+ priv->staging_rxon.ofdm_basic_rates =
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
@@ -1397,7 +1356,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_irq_handle_error);
-int iwl_apm_stop_master(struct iwl_priv *priv)
+static int iwl_apm_stop_master(struct iwl_priv *priv)
{
int ret = 0;
@@ -1413,7 +1372,6 @@ int iwl_apm_stop_master(struct iwl_priv *priv)
return ret;
}
-EXPORT_SYMBOL(iwl_apm_stop_master);
void iwl_apm_stop(struct iwl_priv *priv)
{
@@ -1664,277 +1622,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
}
EXPORT_SYMBOL(iwl_set_tx_power);
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
-
-/* Free dram table */
-void iwl_free_isr_ict(struct iwl_priv *priv)
-{
- if (priv->ict_tbl_vir) {
- dma_free_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- priv->ict_tbl_vir, priv->ict_tbl_dma);
- priv->ict_tbl_vir = NULL;
- }
-}
-EXPORT_SYMBOL(iwl_free_isr_ict);
-
-
-/* allocate dram shared table it is a PAGE_SIZE aligned
- * also reset all data related to ICT table interrupt.
- */
-int iwl_alloc_isr_ict(struct iwl_priv *priv)
-{
-
- if (priv->cfg->use_isr_legacy)
- return 0;
- /* allocate shrared data table */
- priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
- (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
- &priv->ict_tbl_dma, GFP_KERNEL);
- if (!priv->ict_tbl_vir)
- return -ENOMEM;
-
- /* align table to PAGE_SIZE boundry */
- priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
-
- IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
- (unsigned long long)priv->ict_tbl_dma,
- (unsigned long long)priv->aligned_ict_tbl_dma,
- (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
-
- priv->ict_tbl = priv->ict_tbl_vir +
- (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma);
-
- IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
- priv->ict_tbl, priv->ict_tbl_vir,
- (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
-
- /* reset table and index to all 0 */
- memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
- priv->ict_index = 0;
-
- /* add periodic RX interrupt */
- priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
- return 0;
-}
-EXPORT_SYMBOL(iwl_alloc_isr_ict);
-
-/* Device is going up inform it about using ICT interrupt table,
- * also we need to tell the driver to start using ICT interrupt.
- */
-int iwl_reset_ict(struct iwl_priv *priv)
-{
- u32 val;
- unsigned long flags;
-
- if (!priv->ict_tbl_vir)
- return 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_disable_interrupts(priv);
-
- memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
-
- val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
-
- val |= CSR_DRAM_INT_TBL_ENABLE;
- val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
-
- IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
- "aligned dma address %Lx\n",
- val, (unsigned long long)priv->aligned_ict_tbl_dma);
-
- iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
- priv->use_ict = true;
- priv->ict_index = 0;
- iwl_write32(priv, CSR_INT, priv->inta_mask);
- iwl_enable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(iwl_reset_ict);
-
-/* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->use_ict = false;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-EXPORT_SYMBOL(iwl_disable_ict);
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-irqreturn_t iwl_isr_ict(int irq, void *data)
-{
- struct iwl_priv *priv = data;
- u32 inta, inta_mask;
- u32 val = 0;
-
- if (!priv)
- return IRQ_NONE;
-
- /* dram interrupt table not set yet,
- * use legacy interrupt.
- */
- if (!priv->use_ict)
- return iwl_isr(irq, data);
-
- spin_lock(&priv->lock);
-
- /* Disable (but don't clear!) interrupts here to avoid
- * back-to-back ISRs and sporadic interrupts from our NIC.
- * If we have something to service, the tasklet will re-enable ints.
- * If we *don't* have something, we'll re-enable before leaving here.
- */
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-
- /* Ignore interrupt if there's nothing in NIC to service.
- * This may be due to IRQ shared with another device,
- * or due to sporadic interrupts thrown from our NIC. */
- if (!priv->ict_tbl[priv->ict_index]) {
- IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
- goto none;
- }
-
- /* read all entries that not 0 start with ict_index */
- while (priv->ict_tbl[priv->ict_index]) {
-
- val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
- IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
- priv->ict_index,
- le32_to_cpu(priv->ict_tbl[priv->ict_index]));
- priv->ict_tbl[priv->ict_index] = 0;
- priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
- ICT_COUNT);
-
- }
-
- /* We should not get this value, just ignore it. */
- if (val == 0xffffffff)
- val = 0;
-
- /*
- * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
- * (bit 15 before shifting it to 31) to clear when using interrupt
- * coalescing. fortunately, bits 18 and 19 stay set when this happens
- * so we use them to decide on the real state of the Rx bit.
- * In order words, bit 15 is set if bit 18 or bit 19 are set.
- */
- if (val & 0xC0000)
- val |= 0x8000;
-
- inta = (0xff & val) | ((0xff00 & val) << 16);
- IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
- inta, inta_mask, val);
-
- inta &= priv->inta_mask;
- priv->inta |= inta;
-
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
- if (likely(inta))
- tasklet_schedule(&priv->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) {
- /* Allow interrupt if was disabled by this handler and
- * no tasklet was schedules, We should not enable interrupt,
- * tasklet will enable it.
- */
- iwl_enable_interrupts(priv);
- }
-
- spin_unlock(&priv->lock);
- return IRQ_HANDLED;
-
- none:
- /* re-enable interrupts here since we don't have anything to service.
- * only Re-enable if disabled by irq.
- */
- if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
- iwl_enable_interrupts(priv);
-
- spin_unlock(&priv->lock);
- return IRQ_NONE;
-}
-EXPORT_SYMBOL(iwl_isr_ict);
-
-
-static irqreturn_t iwl_isr(int irq, void *data)
-{
- struct iwl_priv *priv = data;
- u32 inta, inta_mask;
-#ifdef CONFIG_IWLWIFI_DEBUG
- u32 inta_fh;
-#endif
- if (!priv)
- return IRQ_NONE;
-
- spin_lock(&priv->lock);
-
- /* Disable (but don't clear!) interrupts here to avoid
- * back-to-back ISRs and sporadic interrupts from our NIC.
- * If we have something to service, the tasklet will re-enable ints.
- * If we *don't* have something, we'll re-enable before leaving here. */
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* Discover which interrupts are active/pending */
- inta = iwl_read32(priv, CSR_INT);
-
- /* Ignore interrupt if there's nothing in NIC to service.
- * This may be due to IRQ shared with another device,
- * or due to sporadic interrupts thrown from our NIC. */
- if (!inta) {
- IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
- goto none;
- }
-
- if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
- /* Hardware disappeared. It might have already raised
- * an interrupt */
- IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
- goto unplugged;
- }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
- IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
- "fh 0x%08x\n", inta, inta_mask, inta_fh);
- }
-#endif
-
- priv->inta |= inta;
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
- if (likely(inta))
- tasklet_schedule(&priv->irq_tasklet);
- else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
- iwl_enable_interrupts(priv);
-
- unplugged:
- spin_unlock(&priv->lock);
- return IRQ_HANDLED;
-
- none:
- /* re-enable interrupts here since we don't have anything to service. */
- /* only Re-enable if diabled by irq and no schedules tasklet. */
- if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
- iwl_enable_interrupts(priv);
-
- spin_unlock(&priv->lock);
- return IRQ_NONE;
-}
-
irqreturn_t iwl_isr_legacy(int irq, void *data)
{
struct iwl_priv *priv = data;
@@ -2564,11 +2251,6 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
return -EIO;
}
- if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
- IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
- return -EIO;
- }
-
spin_lock_irqsave(&priv->lock, flags);
if (priv->ibss_beacon)
@@ -2592,23 +2274,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
}
EXPORT_SYMBOL(iwl_mac_beacon_update);
-int iwl_set_mode(struct iwl_priv *priv, int mode)
+static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
- if (mode == NL80211_IFTYPE_ADHOC) {
- const struct iwl_channel_info *ch_info;
-
- ch_info = iwl_get_channel_info(priv,
- priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
-
- if (!ch_info || !is_channel_ibss(ch_info)) {
- IWL_ERR(priv, "channel %d not IBSS channel\n",
- le16_to_cpu(priv->staging_rxon.channel));
- return -EINVAL;
- }
- }
-
- iwl_connection_init_rx_config(priv, mode);
+ iwl_connection_init_rx_config(priv, vif->type);
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv);
@@ -2617,18 +2285,10 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
iwl_clear_stations_table(priv);
- /* dont commit rxon if rf-kill is on*/
- if (!iwl_is_ready_rf(priv))
- return -EAGAIN;
-
- iwlcore_commit_rxon(priv);
-
- return 0;
+ return iwlcore_commit_rxon(priv);
}
-EXPORT_SYMBOL(iwl_set_mode);
-int iwl_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
int err = 0;
@@ -2637,6 +2297,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
+ if (WARN_ON(!iwl_is_ready_rf(priv))) {
+ err = -EINVAL;
+ goto out;
+ }
+
if (priv->vif) {
IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
err = -EOPNOTSUPP;
@@ -2646,15 +2311,17 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
priv->vif = vif;
priv->iw_mode = vif->type;
- if (vif->addr) {
- IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
- memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
- }
+ IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
+ memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
- if (iwl_set_mode(priv, vif->type) == -EAGAIN)
- /* we are not ready, will run again when ready */
- set_bit(STATUS_MODE_PENDING, &priv->status);
+ err = iwl_set_mode(priv, vif);
+ if (err)
+ goto out_err;
+ goto out;
+ out_err:
+ priv->vif = NULL;
+ priv->iw_mode = NL80211_IFTYPE_STATION;
out:
mutex_unlock(&priv->mutex);
@@ -2664,7 +2331,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
EXPORT_SYMBOL(iwl_mac_add_interface);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
@@ -2748,15 +2415,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
goto set_ch_out;
}
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
- !is_channel_ibss(ch_info)) {
- IWL_ERR(priv, "channel %d in band %d not "
- "IBSS channel\n",
- conf->channel->hw_value, conf->channel->band);
- ret = -EINVAL;
- goto set_ch_out;
- }
-
spin_lock_irqsave(&priv->lock, flags);
/* Configure HT40 channels */
@@ -2878,8 +2536,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
priv->beacon_int = priv->vif->bss_conf.beacon_int;
priv->timestamp = 0;
- if ((priv->iw_mode == NL80211_IFTYPE_STATION))
- priv->beacon_int = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -2892,17 +2548,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
- if (priv->iw_mode != NL80211_IFTYPE_AP) {
- iwl_scan_cancel_timeout(priv, 100);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
- }
-
- if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
- IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
- mutex_unlock(&priv->mutex);
- return;
- }
+ iwl_scan_cancel_timeout(priv, 100);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwlcore_commit_rxon(priv);
iwl_set_rate(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4ef7739f9e8..aced12f1611 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -336,7 +336,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
int iwl_commit_rxon(struct iwl_priv *priv);
-int iwl_set_mode(struct iwl_priv *priv, int mode);
int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
@@ -560,11 +559,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
* PCI *
*****************************************************/
irqreturn_t iwl_isr_legacy(int irq, void *data);
-int iwl_reset_ict(struct iwl_priv *priv);
-void iwl_disable_ict(struct iwl_priv *priv);
-int iwl_alloc_isr_ict(struct iwl_priv *priv);
-void iwl_free_isr_ict(struct iwl_priv *priv);
-irqreturn_t iwl_isr_ict(int irq, void *data);
static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
{
@@ -622,7 +616,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
#define STATUS_SCAN_HW 15
#define STATUS_POWER_PMI 16
#define STATUS_FW_ERROR 17
-#define STATUS_MODE_PENDING 18
static inline int iwl_is_ready(struct iwl_priv *priv)
@@ -682,7 +675,6 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwl_apm_stop(struct iwl_priv *priv);
-int iwl_apm_stop_master(struct iwl_priv *priv);
int iwl_apm_init(struct iwl_priv *priv);
void iwl_setup_rxon_timing(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7bf44f14679..5f5820249a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -560,8 +560,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
test_bit(STATUS_POWER_PMI, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
test_bit(STATUS_FW_ERROR, &priv->status));
- pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
- test_bit(STATUS_MODE_PENDING, &priv->status));
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -660,7 +658,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
int pos = 0, i;
char buf[256];
const size_t bufsz = sizeof(buf);
- ssize_t ret;
for (i = 0; i < AC_NUM; i++) {
pos += scnprintf(buf + pos, bufsz - pos,
@@ -672,8 +669,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
priv->qos_data.def_qos_parm.ac[i].aifsn,
priv->qos_data.def_qos_parm.ac[i].edca_txop);
}
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
@@ -683,7 +679,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
int pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos,
"allow blinking: %s\n",
@@ -697,8 +692,7 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
priv->last_blink_time);
}
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
@@ -711,7 +705,6 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
char buf[100];
int pos = 0;
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos,
"Thermal Throttling Mode: %s\n",
@@ -731,8 +724,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
"HT mode: %d\n",
restriction->is_ht);
}
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
@@ -769,13 +761,11 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
char buf[100];
int pos = 0;
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos,
"11n 40MHz Mode: %s\n",
priv->disable_ht40 ? "Disabled" : "Enabled");
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
@@ -2051,7 +2041,6 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
int pos = 0;
char buf[128];
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
priv->event_log.ucode_trace ? "On" : "Off");
@@ -2062,8 +2051,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
priv->event_log.wraps_more_count);
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
@@ -2095,6 +2083,31 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int len = 0;
+ char buf[20];
+
+ len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int len = 0;
+ char buf[20];
+
+ len = sprintf(buf, "0x%04X\n",
+ le32_to_cpu(priv->active_rxon.filter_flags));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -2124,13 +2137,11 @@ static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
int pos = 0;
char buf[12];
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
priv->missed_beacon_threshold);
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
@@ -2159,27 +2170,6 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
return count;
}
-static ssize_t iwl_dbgfs_internal_scan_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_priv *priv = file->private_data;
- char buf[8];
- int buf_size;
- int scan;
-
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- if (sscanf(buf, "%d", &scan) != 1)
- return -EINVAL;
-
- iwl_internal_short_hw_scan(priv);
-
- return count;
-}
-
static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
@@ -2188,13 +2178,11 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
int pos = 0;
char buf[12];
const size_t bufsz = sizeof(buf);
- ssize_t ret;
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
priv->cfg->plcp_delta_threshold);
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
- return ret;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
@@ -2295,9 +2283,10 @@ DEBUGFS_WRITE_FILE_OPS(csr);
DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
DEBUGFS_READ_FILE_OPS(fh_reg);
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_WRITE_FILE_OPS(internal_scan);
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
+DEBUGFS_READ_FILE_OPS(rxon_flags);
+DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
/*
* Create the debugfs files and directories
@@ -2349,7 +2338,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
- DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
@@ -2360,6 +2348,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
}
+ DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
+ DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
&priv->disable_chain_noise_cal);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6054c5fba0c..2e4d47c7139 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -304,13 +304,11 @@ struct iwl_channel_info {
struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
};
-#define IWL_TX_FIFO_AC0 0
-#define IWL_TX_FIFO_AC1 1
-#define IWL_TX_FIFO_AC2 2
-#define IWL_TX_FIFO_AC3 3
-#define IWL_TX_FIFO_HCCA_1 5
-#define IWL_TX_FIFO_HCCA_2 6
-#define IWL_TX_FIFO_NONE 7
+#define IWL_TX_FIFO_BK 0
+#define IWL_TX_FIFO_BE 1
+#define IWL_TX_FIFO_VI 2
+#define IWL_TX_FIFO_VO 3
+#define IWL_TX_FIFO_UNUSED -1
/* Minimum number of queues. MAX_NUM is defined in hw specific files.
* Set the minimum to accommodate the 4 standard TX queues, 1 command
@@ -1092,10 +1090,6 @@ struct iwl_priv {
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */
- /* each calibration channel group in the EEPROM has a derived
- * clip setting for each rate. 3945 only.*/
- const struct iwl3945_clip_group clip39_groups[5];
-
/* thermal calibration */
s32 temperature; /* degrees Kelvin */
s32 last_temperature;
@@ -1168,7 +1162,6 @@ struct iwl_priv {
u64 led_tpt;
u16 active_rate;
- u16 active_rate_basic;
u8 assoc_station_added;
u8 start_calib;
@@ -1197,7 +1190,6 @@ struct iwl_priv {
unsigned long status;
- int last_rx_rssi; /* From Rx packet statistics */
int last_rx_noise; /* From beacon statistics */
/* counts mgmt, ctl, and data packets */
@@ -1218,8 +1210,6 @@ struct iwl_priv {
#endif
/* context information */
- u16 rates_mask;
-
u8 bssid[ETH_ALEN];
u16 rts_threshold;
u8 mac_addr[ETH_ALEN];
@@ -1228,7 +1218,7 @@ struct iwl_priv {
spinlock_t sta_lock;
int num_stations;
struct iwl_station_entry stations[IWL_STATION_COUNT];
- struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
+ struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
u8 default_wep_key;
u8 key_mapping_key;
unsigned long ucode_key_table;
@@ -1244,10 +1234,6 @@ struct iwl_priv {
u8 mac80211_registered;
- /* Rx'd packet timing information */
- u32 last_beacon_time;
- u64 last_tsf;
-
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
int nvm_device_type;
@@ -1262,20 +1248,48 @@ struct iwl_priv {
u16 beacon_int;
struct ieee80211_vif *vif;
- /*Added for 3945 */
- void *shared_virt;
- dma_addr_t shared_phys;
- /*End*/
- struct iwl_hw_params hw_params;
+ union {
+#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
+ struct {
+ void *shared_virt;
+ dma_addr_t shared_phys;
+
+ struct delayed_work thermal_periodic;
+ struct delayed_work rfkill_poll;
+
+ struct iwl3945_notif_statistics statistics;
+
+ u32 sta_supp_rates;
+ int last_rx_rssi; /* From Rx packet statistics */
+
+ /* Rx'd packet timing information */
+ u32 last_beacon_time;
+ u64 last_tsf;
- /* INT ICT Table */
- __le32 *ict_tbl;
- dma_addr_t ict_tbl_dma;
- dma_addr_t aligned_ict_tbl_dma;
- int ict_index;
- void *ict_tbl_vir;
- u32 inta;
- bool use_ict;
+ /*
+ * each calibration channel group in the
+ * EEPROM has a derived clip setting for
+ * each rate.
+ */
+ const struct iwl3945_clip_group clip_groups[5];
+
+ } _3945;
+#endif
+#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE)
+ struct {
+ /* INT ICT Table */
+ __le32 *ict_tbl;
+ void *ict_tbl_vir;
+ dma_addr_t ict_tbl_dma;
+ dma_addr_t aligned_ict_tbl_dma;
+ int ict_index;
+ u32 inta;
+ bool use_ict;
+ } _agn;
+#endif
+ };
+
+ struct iwl_hw_params hw_params;
u32 inta_mask;
/* Current association information needed to configure the
@@ -1303,10 +1317,6 @@ struct iwl_priv {
struct delayed_work alive_start;
struct delayed_work scan_check;
- /*For 3945 only*/
- struct delayed_work thermal_periodic;
- struct delayed_work rfkill_poll;
-
/* TX Power */
s8 tx_power_user_lmt;
s8 tx_power_device_lmt;
@@ -1339,12 +1349,6 @@ struct iwl_priv {
struct timer_list statistics_periodic;
struct timer_list ucode_trace;
bool hw_ready;
- /*For 3945*/
-#define IWL_DEFAULT_TX_POWER 0x0F
-
- struct iwl3945_notif_statistics statistics_39;
-
- u32 sta_supp_rates;
struct iwl_event_log event_log;
}; /*iwl_priv */
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 51a67fb2e18..3ff6b9d25a1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -31,6 +31,9 @@
#define __iwl_helpers_h__
#include <linux/ctype.h>
+#include <net/mac80211.h>
+
+#include "iwl-io.h"
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index d2d2a917490..5944de7a98a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -254,7 +254,7 @@
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
* but one DMA channel may take input from several queues.
*
- * Tx DMA channels have dedicated purposes. For 4965, they are used as follows
+ * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows
* (cf. default_queue_to_tx_fifo in iwl-4965.c):
*
* 0 -- EDCA BK (background) frames, lowest priority
@@ -262,20 +262,20 @@
* 2 -- EDCA VI (video) frames, higher priority
* 3 -- EDCA VO (voice) and management frames, highest priority
* 4 -- Commands (e.g. RXON, etc.)
- * 5 -- HCCA short frames
- * 6 -- HCCA long frames
+ * 5 -- unused (HCCA)
+ * 6 -- unused (HCCA)
* 7 -- not used by driver (device-internal only)
*
- * For 5000 series and up, they are used slightly differently
+ * For 5000 series and up, they are used differently
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
*
* 0 -- EDCA BK (background) frames, lowest priority
* 1 -- EDCA BE (best effort) frames, normal priority
* 2 -- EDCA VI (video) frames, higher priority
* 3 -- EDCA VO (voice) and management frames, highest priority
- * 4 -- (TBD)
- * 5 -- HCCA short frames
- * 6 -- HCCA long frames
+ * 4 -- unused
+ * 5 -- unused
+ * 6 -- unused
* 7 -- Commands
*
* Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index df257bc15f4..8116aa0d767 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1036,24 +1036,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
rxb->page = NULL;
}
-/* This is necessary only for a number of statistics, see the caller. */
-static int iwl_is_network_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header)
-{
- /* Filter incoming packets to determine if they are targeted toward
- * this network, discarding packets coming from ourselves */
- switch (priv->iw_mode) {
- case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
- /* packets to our IBSS update information */
- return !compare_ether_addr(header->addr3, priv->bssid);
- case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
- /* packets to our IBSS update information */
- return !compare_ether_addr(header->addr2, priv->bssid);
- default:
- return 1;
- }
-}
-
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
void iwl_rx_reply_rx(struct iwl_priv *priv,
@@ -1190,12 +1172,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
if (rate_n_flags & RATE_MCS_SGI_MSK)
rx_status.flag |= RX_FLAG_SHORT_GI;
- if (iwl_is_network_packet(priv, header)) {
- priv->last_rx_rssi = rx_status.signal;
- priv->last_beacon_time = priv->ucode_beacon_time;
- priv->last_tsf = le64_to_cpu(phy_res->timestamp);
- }
-
iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
rxb, &rx_status);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index bd2f7c42056..84b19b12ff0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -580,7 +580,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
out:
return ret;
}
-EXPORT_SYMBOL(iwl_internal_short_hw_scan);
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
@@ -665,7 +664,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
};
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
- int ret = 0;
u32 rate_flags = 0;
u16 cmd_len;
u16 rx_chain = 0;
@@ -698,7 +696,6 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
"Ignoring second request.\n");
- ret = -EIO;
goto done;
}
@@ -731,7 +728,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
- ret = -ENOMEM;
+ IWL_DEBUG_SCAN(priv,
+ "fail to allocate memory for scan\n");
goto done;
}
}
@@ -892,8 +890,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- ret = iwl_send_cmd_sync(priv, &cmd);
- if (ret)
+ if (iwl_send_cmd_sync(priv, &cmd))
goto done;
queue_delayed_work(priv->workqueue, &priv->scan_check,
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 4a6686fa6b3..b1aad306efa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -549,9 +549,11 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY,
.data = wep_cmd,
- .flags = CMD_ASYNC,
+ .flags = CMD_SYNC,
};
+ might_sleep();
+
memset(wep_cmd, 0, cmd_size +
(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
@@ -587,9 +589,9 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf)
{
int ret;
- unsigned long flags;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ WARN_ON(!mutex_is_locked(&priv->mutex));
+
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx);
@@ -601,13 +603,12 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ /* but keys in device are clear anyway so return success */
return 0;
}
ret = iwl_send_static_wepkey_cmd(priv, 1);
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
keyconf->keyidx, ret);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
@@ -617,7 +618,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf)
{
int ret;
- unsigned long flags;
+
+ WARN_ON(!mutex_is_locked(&priv->mutex));
if (keyconf->keylen != WEP_KEY_LEN_128 &&
keyconf->keylen != WEP_KEY_LEN_64) {
@@ -629,12 +631,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
keyconf->hw_key_idx = HW_KEY_DEFAULT;
priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
- spin_lock_irqsave(&priv->sta_lock, flags);
priv->default_wep_key++;
if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
IWL_ERR(priv, "index %d already used in uCode key table.\n",
- keyconf->keyidx);
+ keyconf->keyidx);
priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
@@ -643,7 +644,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
ret = iwl_send_static_wepkey_cmd(priv, 0);
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
keyconf->keylen, keyconf->keyidx, ret);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 8c12311dbb0..d6222aabe6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -37,26 +37,63 @@
#include "iwl-io.h"
#include "iwl-helpers.h"
-static const u16 default_tid_to_tx_fifo[] = {
- IWL_TX_FIFO_AC1,
- IWL_TX_FIFO_AC0,
- IWL_TX_FIFO_AC0,
- IWL_TX_FIFO_AC1,
- IWL_TX_FIFO_AC2,
- IWL_TX_FIFO_AC2,
- IWL_TX_FIFO_AC3,
- IWL_TX_FIFO_AC3,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_NONE,
- IWL_TX_FIFO_AC3
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ * VO 0
+ * VI 1
+ * BE 2
+ * BK 3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific modules like
+ * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
+ * mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+ /* this matches the mac80211 numbers */
+ 2, 3, 3, 2, 1, 1, 0, 0
+};
+
+static const u8 ac_to_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
};
+static inline int get_fifo_from_ac(u8 ac)
+{
+ return ac_to_fifo[ac];
+}
+
+static inline int get_queue_from_ac(u16 ac)
+{
+ return ac;
+}
+
+static inline int get_fifo_from_tid(u16 tid)
+{
+ if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+ return get_fifo_from_ac(tid_to_ac[tid]);
+
+ /* no support for TIDs 8-15 yet */
+ return -EINVAL;
+}
+
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
struct iwl_dma_ptr *ptr, size_t size)
{
@@ -591,13 +628,12 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->next_frame_len = 0;
}
-#define RTS_HCCA_RETRY_LIMIT 3
#define RTS_DFAULT_RETRY_LIMIT 60
static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info,
- __le16 fc, int is_hcca)
+ __le16 fc)
{
u32 rate_flags;
int rate_idx;
@@ -613,8 +649,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
tx_cmd->data_retry_limit = data_retry_limit;
/* Set retry limit on RTS packets */
- rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT :
- RTS_DFAULT_RETRY_LIMIT;
+ rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
if (data_retry_limit < rts_retry_limit)
rts_retry_limit = data_retry_limit;
tx_cmd->rts_retry_limit = rts_retry_limit;
@@ -761,16 +796,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
#endif
- /* drop all non-injected data frame if we are not associated */
- if (ieee80211_is_data(fc) &&
- !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
- (!iwl_is_associated(priv) ||
- ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
- !priv->assoc_station_added)) {
- IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
- goto drop_unlock;
- }
-
hdr_len = ieee80211_hdrlen(fc);
/* Find (or create) index into station table for destination station */
@@ -804,7 +829,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
}
- txq_id = skb_get_queue_mapping(skb);
+ txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
@@ -869,8 +894,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
iwl_dbg_log_tx_data_frame(priv, len, hdr);
- /* set is_hcca to 0; it probably will never be implemented */
- iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0);
+ iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc);
iwl_update_stats(priv, true, fc, len);
/*
@@ -1270,7 +1294,7 @@ EXPORT_SYMBOL(iwl_tx_cmd_complete);
* Find first available (lowest unused) Tx Queue, mark it "active".
* Called only when finding queue for aggregation.
* Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
*/
static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
{
@@ -1291,10 +1315,9 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
unsigned long flags;
struct iwl_tid_data *tid_data;
- if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
- tx_fifo = default_tid_to_tx_fifo[tid];
- else
- return -EINVAL;
+ tx_fifo = get_fifo_from_tid(tid);
+ if (unlikely(tx_fifo < 0))
+ return tx_fifo;
IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
__func__, ra, tid);
@@ -1355,13 +1378,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
return -EINVAL;
}
- if (unlikely(tid >= MAX_TID_COUNT))
- return -EINVAL;
-
- if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
- tx_fifo_id = default_tid_to_tx_fifo[tid];
- else
- return -EINVAL;
+ tx_fifo_id = get_fifo_from_tid(tid);
+ if (unlikely(tx_fifo_id < 0))
+ return tx_fifo_id;
sta_id = iwl_find_station(priv, ra);
@@ -1429,7 +1448,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
if ((txq_id == tid_data->agg.txq_id) &&
(q->read_ptr == q->write_ptr)) {
u16 ssn = SEQ_TO_SN(tid_data->seq_number);
- int tx_fifo = default_tid_to_tx_fifo[tid];
+ int tx_fifo = get_fifo_from_tid(tid);
IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
ssn, tx_fifo);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 54daa38ecba..2579bbcaab3 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -351,11 +351,11 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
{
- if (priv->shared_virt)
+ if (priv->_3945.shared_virt)
dma_free_coherent(&priv->pci_dev->dev,
sizeof(struct iwl3945_shared),
- priv->shared_virt,
- priv->shared_phys);
+ priv->_3945.shared_virt,
+ priv->_3945.shared_phys);
}
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
@@ -504,15 +504,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
#endif
- /* drop all non-injected data frame if we are not associated */
- if (ieee80211_is_data(fc) &&
- !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
- (!iwl_is_associated(priv) ||
- ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
- IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
- goto drop_unlock;
- }
-
spin_unlock_irqrestore(&priv->lock, flags);
hdr_len = ieee80211_hdrlen(fc);
@@ -753,7 +744,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
if (iwl_is_associated(priv))
add_time =
iwl3945_usecs_to_beacons(
- le64_to_cpu(params->start_time) - priv->last_tsf,
+ le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
le16_to_cpu(priv->rxon_timing.beacon_interval));
memset(&spectrum, 0, sizeof(spectrum));
@@ -767,7 +758,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
if (iwl_is_associated(priv))
spectrum.start_time =
- iwl3945_add_beacon_time(priv->last_beacon_time,
+ iwl3945_add_beacon_time(priv->_3945.last_beacon_time,
add_time,
le16_to_cpu(priv->rxon_timing.beacon_interval));
else
@@ -2517,8 +2508,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
ieee80211_wake_queues(priv->hw);
- priv->active_rate = priv->rates_mask;
- priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
+ priv->active_rate = IWL_RATES_MASK;
iwl_power_update_mode(priv, true);
@@ -2547,17 +2537,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
set_bit(STATUS_READY, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
- /* reassociate for ADHOC mode */
- if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
- struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
- priv->vif);
- if (beacon)
- iwl_mac_beacon_update(priv->hw, beacon);
- }
-
- if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
- iwl_set_mode(priv, priv->iw_mode);
-
return;
restart:
@@ -2718,7 +2697,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
* prepare to load the "initialize" uCode */
- priv->cfg->ops->lib->load_ucode(priv);
+ rc = priv->cfg->ops->lib->load_ucode(priv);
if (rc) {
IWL_ERR(priv,
@@ -2786,7 +2765,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
static void iwl3945_rfkill_poll(struct work_struct *data)
{
struct iwl_priv *priv =
- container_of(data, struct iwl_priv, rfkill_poll.work);
+ container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
@@ -2805,7 +2784,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
/* Keep this running, even if radio now enabled. This will be
* cancelled in mac_start() if system decides to start again */
- queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+ queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
round_jiffies_relative(2 * HZ));
}
@@ -2820,7 +2799,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
.len = sizeof(struct iwl3945_scan_cmd),
.flags = CMD_SIZE_HUGE,
};
- int rc = 0;
struct iwl3945_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u8 n_probes = 0;
@@ -2848,7 +2826,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests "
"Ignoring second request.\n");
- rc = -EIO;
goto done;
}
@@ -2883,7 +2860,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
- rc = -ENOMEM;
+ IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
goto done;
}
}
@@ -2926,7 +2903,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan_suspend_time, interval);
}
- if (priv->scan_request->n_ssids) {
+ if (priv->is_internal_short_scan) {
+ IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+ } else if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -2973,13 +2952,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
goto done;
}
- scan->tx_cmd.len = cpu_to_le16(
+ if (!priv->is_internal_short_scan) {
+ scan->tx_cmd.len = cpu_to_le16(
iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-
+ } else {
+ scan->tx_cmd.len = cpu_to_le16(
+ iwl_fill_probe_req(priv,
+ (struct ieee80211_mgmt *)scan->data,
+ NULL, 0,
+ IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+ }
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
@@ -3001,8 +2987,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc)
+ if (iwl_send_cmd_sync(priv, &cmd))
goto done;
queue_delayed_work(priv->workqueue, &priv->scan_check,
@@ -3212,7 +3197,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
/* ucode is running and will send rfkill notifications,
* no need to poll the killswitch state anymore */
- cancel_delayed_work(&priv->rfkill_poll);
+ cancel_delayed_work(&priv->_3945.rfkill_poll);
iwl_led_start(priv);
@@ -3253,7 +3238,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
flush_workqueue(priv->workqueue);
/* start polling the killswitch state again */
- queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+ queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
round_jiffies_relative(2 * HZ));
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3365,7 +3350,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100);
- mutex_unlock(&priv->mutex);
switch (cmd) {
case SET_KEY:
@@ -3386,6 +3370,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = -EINVAL;
}
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
@@ -3590,7 +3575,7 @@ static ssize_t store_measurement(struct device *d,
struct iwl_priv *priv = dev_get_drvdata(d);
struct ieee80211_measurement_params params = {
.channel = le16_to_cpu(priv->active_rxon.channel),
- .start_time = cpu_to_le64(priv->last_tsf),
+ .start_time = cpu_to_le64(priv->_3945.last_tsf),
.duration = cpu_to_le16(1),
};
u8 type = IWL_MEASURE_BASIC;
@@ -3660,7 +3645,7 @@ static ssize_t show_statistics(struct device *d,
struct iwl_priv *priv = dev_get_drvdata(d);
u32 size = sizeof(struct iwl3945_notif_statistics);
u32 len = 0, ofs = 0;
- u8 *data = (u8 *)&priv->statistics_39;
+ u8 *data = (u8 *)&priv->_3945.statistics;
int rc = 0;
if (!iwl_is_alive(priv))
@@ -3773,7 +3758,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
- INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll);
+ INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
@@ -3864,7 +3849,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
- priv->rates_mask = IWL_RATES_MASK;
priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -4129,7 +4113,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
/* Start monitoring the killswitch */
- queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
+ queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
2 * HZ);
return 0;
@@ -4203,7 +4187,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- cancel_delayed_work_sync(&priv->rfkill_poll);
+ cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
iwl3945_dealloc_ucode_pci(priv);