summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c751
1 files changed, 351 insertions, 400 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 45a6b0c3569..d64580805d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -41,6 +41,7 @@
#include <linux/if_arp.h>
#include <net/ieee80211_radiotap.h>
+#include <net/lib80211.h>
#include <net/mac80211.h>
#include <asm/div64.h>
@@ -64,11 +65,10 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
/* module parameters */
static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */
-static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */
+static u32 iwl3945_param_debug; /* def: 0 = minimal debug log messages */
static int iwl3945_param_disable; /* def: 0 = enable radio */
static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
-static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
/*
@@ -93,12 +93,13 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
#define IWLWIFI_VERSION "1.2.26k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
+#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define DRV_VERSION IWLWIFI_VERSION
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
static const struct ieee80211_supported_band *iwl3945_get_band(
@@ -107,46 +108,6 @@ static const struct ieee80211_supported_band *iwl3945_get_band(
return priv->hw->wiphy->bands[band];
}
-static int iwl3945_is_empty_essid(const char *essid, int essid_len)
-{
- /* Single white space is for Linksys APs */
- if (essid_len == 1 && essid[0] == ' ')
- return 1;
-
- /* Otherwise, if the entire essid is 0, we assume it is hidden */
- while (essid_len) {
- essid_len--;
- if (essid[essid_len] != '\0')
- return 0;
- }
-
- return 1;
-}
-
-static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
-{
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (iwl3945_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else
- *d++ = *s++;
- }
- *d = '\0';
- return escaped;
-}
-
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -446,7 +407,6 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
int index = IWL_INVALID_STATION;
struct iwl3945_station_entry *station;
unsigned long flags_spin;
- DECLARE_MAC_BUF(mac);
u8 rate;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
@@ -480,7 +440,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
return index;
}
- IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
+ IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr);
station = &priv->stations[index];
station->used = 1;
priv->num_stations++;
@@ -559,7 +519,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
-#define IWL_CMD(x) case x : return #x
+#define IWL_CMD(x) case x: return #x
static const char *get_cmd_string(u8 cmd)
{
@@ -1063,7 +1023,6 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
/* cast away the const for active_rxon in this function */
struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
int rc = 0;
- DECLARE_MAC_BUF(mac);
if (!iwl3945_is_alive(priv))
return -1;
@@ -1124,11 +1083,11 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
IWL_DEBUG_INFO("Sending RXON\n"
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
- "* bssid = %s\n",
+ "* bssid = %pM\n",
((priv->staging_rxon.filter_flags &
RXON_FILTER_ASSOC_MSK) ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
- print_mac(mac, priv->staging_rxon.bssid_addr));
+ priv->staging_rxon.bssid_addr);
/* Apply the new configuration */
rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
@@ -1443,7 +1402,7 @@ static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame *
unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr,
- const u8 *dest, int left)
+ int left)
{
if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
@@ -1459,9 +1418,16 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
return priv->ibss_beacon->len;
}
-static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
+static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
{
u8 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;
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
i = iwl3945_rates[i].next_ieee) {
@@ -1469,7 +1435,11 @@ static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
return iwl3945_rates[i].plcp;
}
- return IWL_RATE_INVALID;
+ /* No valid rate was found. Assign the lowest one */
+ if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ return IWL_RATE_1M_PLCP;
+ else
+ return IWL_RATE_6M_PLCP;
}
static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
@@ -1487,16 +1457,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
return -ENOMEM;
}
- if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
- rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic &
- 0xFF0);
- if (rate == IWL_INVALID_RATE)
- rate = IWL_RATE_6M_PLCP;
- } else {
- rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
- if (rate == IWL_INVALID_RATE)
- rate = IWL_RATE_1M_PLCP;
- }
+ rate = iwl3945_rate_get_lowest_plcp(priv);
frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
@@ -1544,10 +1505,8 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
{
u16 *e = (u16 *)&priv->eeprom;
u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
- u32 r;
int sz = sizeof(priv->eeprom);
- int rc;
- int i;
+ int ret;
u16 addr;
/* The EEPROM structure has several padding buffers within it
@@ -1562,29 +1521,28 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
- rc = iwl3945_eeprom_acquire_semaphore(priv);
- if (rc < 0) {
+ ret = iwl3945_eeprom_acquire_semaphore(priv);
+ if (ret < 0) {
IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
return -ENOENT;
}
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
- _iwl3945_write32(priv, CSR_EEPROM_REG, addr << 1);
- _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
-
- for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
- i += IWL_EEPROM_ACCESS_DELAY) {
- r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
- if (r & CSR_EEPROM_REG_READ_VALID_MSK)
- break;
- udelay(IWL_EEPROM_ACCESS_DELAY);
- }
+ u32 r;
- if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
+ _iwl3945_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+ ret = iwl3945_poll_direct_bit(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret < 0) {
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
- return -ETIMEDOUT;
+ return ret;
}
+
+ r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
}
@@ -1634,7 +1592,7 @@ static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate,
*/
static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
struct ieee80211_mgmt *frame,
- int left, int is_direct)
+ int left)
{
int len = 0;
u8 *pos = NULL;
@@ -1664,20 +1622,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
*pos++ = WLAN_EID_SSID;
*pos++ = 0;
- /* fill in our direct SSID IE... */
- if (is_direct) {
- /* ...next IE... */
- left -= 2 + priv->essid_len;
- if (left < 0)
- return 0;
- /* ... fill it in... */
- *pos++ = WLAN_EID_SSID;
- *pos++ = priv->essid_len;
- memcpy(pos, priv->essid, priv->essid_len);
- pos += priv->essid_len;
- len += 2 + priv->essid_len;
- }
-
/* fill in supported rate */
/* ...next IE... */
left -= 2;
@@ -1746,17 +1690,21 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- if (!(priv->active_rate & 0xfff0)) {
- cw_min = 31;
- is_legacy = 1;
- }
- } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
+ /* QoS always active in AP and ADHOC mode
+ * In STA mode wait for association
+ */
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
+ priv->iw_mode == NL80211_IFTYPE_AP)
+ priv->qos_data.qos_active = 1;
+ else
+ priv->qos_data.qos_active = 0;
+
+
+ /* check for legacy mode */
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+ (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
+ (priv->iw_mode == NL80211_IFTYPE_STATION &&
+ (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
cw_min = 31;
is_legacy = 1;
}
@@ -1828,9 +1776,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!priv->qos_data.qos_enable)
- return;
-
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.def_qos_parm.qos_flags = 0;
@@ -1846,7 +1791,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
spin_unlock_irqrestore(&priv->lock, flags);
if (force || iwl3945_is_associated(priv)) {
- IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
+ IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n",
priv->qos_data.qos_active);
iwl3945_send_qos_params_command(priv,
@@ -1870,7 +1815,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
/* default power management (not Tx power) table values */
-/* for tim 0-10 */
+/* for TIM 0-10 */
static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -1880,7 +1825,7 @@ static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
};
-/* for tim > 10 */
+/* for TIM > 10 */
static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
@@ -2156,11 +2101,6 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
- if (priv->iw_mode == NL80211_IFTYPE_AP) {
- IWL_ERROR("APs don't scan.\n");
- return 0;
- }
-
if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
@@ -2230,13 +2170,14 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
/*
* initialize rxon structure with default values from eeprom
*/
-static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
+ int mode)
{
const struct iwl3945_channel_info *ch_info;
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
- switch (priv->iw_mode) {
+ switch (mode) {
case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
@@ -2259,7 +2200,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
break;
default:
- IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+ IWL_ERROR("Unsupported interface type %d\n", mode);
break;
}
@@ -2282,8 +2223,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
* 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)))
+ if ((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);
@@ -2316,14 +2256,12 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
}
}
- priv->iw_mode = mode;
-
- iwl3945_connection_init_rx_config(priv);
+ iwl3945_connection_init_rx_config(priv, mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
iwl3945_clear_stations_table(priv);
- /* dont commit rxon if rf-kill is on*/
+ /* don't commit rxon if rf-kill is on*/
if (!iwl3945_is_ready_rf(priv))
return -EAGAIN;
@@ -2352,7 +2290,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
case ALG_CCMP:
cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
- IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
break;
case ALG_TKIP:
@@ -2397,6 +2335,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
{
__le16 fc = hdr->frame_control;
__le32 tx_flags = cmd->cmd.tx.tx_flags;
+ u8 rc_flags = info->control.rates[0].flags;
cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
@@ -2423,10 +2362,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_flags |= TX_CMD_FLG_RTS_MSK;
tx_flags &= ~TX_CMD_FLG_CTS_MSK;
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
tx_flags &= ~TX_CMD_FLG_RTS_MSK;
tx_flags |= TX_CMD_FLG_CTS_MSK;
}
@@ -2482,8 +2421,6 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
case NL80211_IFTYPE_ADHOC: {
- DECLARE_MAC_BUF(mac);
-
/* Create new station table entry */
sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
@@ -2494,9 +2431,9 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- IWL_DEBUG_DROP("Station %s not in station map. "
+ IWL_DEBUG_DROP("Station %pM not in station map. "
"Defaulting to broadcast...\n",
- print_mac(mac, hdr->addr1));
+ hdr->addr1);
iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
}
@@ -2579,10 +2516,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
/* Find (or create) index into station table for destination station */
sta_id = iwl3945_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+ hdr->addr1);
goto drop;
}
@@ -4019,8 +3954,6 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
#ifdef CONFIG_IWL3945_DEBUG
static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
{
- DECLARE_MAC_BUF(mac);
-
IWL_DEBUG_RADIO("RX CONFIG:\n");
iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
@@ -4031,10 +3964,8 @@ static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
rxon->ofdm_basic_rates);
IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
- IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
- print_mac(mac, rxon->node_addr));
- IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
- print_mac(mac, rxon->bssid_addr));
+ IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+ IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif
@@ -4050,7 +3981,7 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
{
- /* wait to make sure we flush pedding tasklet*/
+ /* wait to make sure we flush pending tasklet*/
synchronize_irq(priv->pci_dev->irq);
tasklet_kill(&priv->irq_tasklet);
}
@@ -4373,35 +4304,6 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
/* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
- /* HW RF KILL switch toggled (4965 only) */
- if (inta & CSR_INT_BIT_RF_KILL) {
- int hw_rf_kill = 0;
- if (!(iwl3945_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
-
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
- "RF_KILL bit toggled to %s.\n",
- hw_rf_kill ? "disable radio":"enable radio");
-
- /* Queue restart only if RF_KILL switch was set to "kill"
- * when we loaded driver, and is now set to "enable".
- * After we're Alive, RF_KILL gets handled by
- * iwl3945_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- }
-
- handled |= CSR_INT_BIT_RF_KILL;
- }
-
- /* Chip got too hot and stopped itself (4965 only) */
- if (inta & CSR_INT_BIT_CT_KILL) {
- IWL_ERROR("Microcode CT kill error detected.\n");
- handled |= CSR_INT_BIT_CT_KILL;
- }
-
/* Error detected by uCode */
if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n",
@@ -4502,7 +4404,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
- IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
+ IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
@@ -4805,7 +4707,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
-#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+#define IWL_SCAN_PROBE_MASK(n) (BIT(n) | (BIT(n) - BIT(1)))
static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
enum ieee80211_band band,
@@ -4876,17 +4778,33 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
continue;
}
+ scan_ch->active_dwell = cpu_to_le16(active_dwell);
+ scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* If passive , set up for auto-switch
+ * and use long active_dwell time.
+ */
if (!is_active || is_channel_passive(ch_info) ||
- (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
scan_ch->type = 0; /* passive */
- else
+ if (IWL_UCODE_API(priv->ucode_ver) == 1)
+ scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
+ } else {
scan_ch->type = 1; /* active */
+ }
- if ((scan_ch->type & 1) && n_probes)
- scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* Set direct probe bits. These may be used both for active
+ * scan channels (probes gets sent right away),
+ * or for passive channels (probes get se sent only after
+ * hearing clear Rx packet).*/
+ if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ if (n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+ } else {
+ /* uCode v1 does not allow setting direct probe bits on
+ * passive channel. */
+ if ((scan_ch->type & 1) && n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+ }
/* Set txpower levels to defaults */
scan_ch->tpc.dsp_atten = 110;
@@ -5387,25 +5305,41 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
static int iwl3945_read_ucode(struct iwl3945_priv *priv)
{
struct iwl3945_ucode *ucode;
- int ret = 0;
+ int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
- const char *name = priv->cfg->fw_name;
+ const char *name_pre = priv->cfg->fw_name_pre;
+ const unsigned int api_max = priv->cfg->ucode_api_max;
+ const unsigned int api_min = priv->cfg->ucode_api_min;
+ char buf[25];
u8 *src;
size_t len;
- u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
- ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
- if (ret < 0) {
- IWL_ERROR("%s firmware file req failed: Reason %d\n",
- name, ret);
- goto error;
+ for (index = api_max; index >= api_min; index--) {
+ sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
+ ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+ if (ret < 0) {
+ IWL_ERROR("%s firmware file req failed: Reason %d\n",
+ buf, ret);
+ if (ret == -ENOENT)
+ continue;
+ else
+ goto error;
+ } else {
+ if (index < api_max)
+ IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+ buf, api_max);
+ IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
+ buf, ucode_raw->size);
+ break;
+ }
}
- IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
- name, ucode_raw->size);
+ if (ret < 0)
+ goto error;
/* Make sure that we got at least our header! */
if (ucode_raw->size < sizeof(*ucode)) {
@@ -5417,20 +5351,46 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
/* Data from ucode file: header followed by uCode images */
ucode = (void *)ucode_raw->data;
- ver = le32_to_cpu(ucode->ver);
+ priv->ucode_ver = le32_to_cpu(ucode->ver);
+ api_ver = IWL_UCODE_API(priv->ucode_ver);
inst_size = le32_to_cpu(ucode->inst_size);
data_size = le32_to_cpu(ucode->data_size);
init_size = le32_to_cpu(ucode->init_size);
init_data_size = le32_to_cpu(ucode->init_data_size);
boot_size = le32_to_cpu(ucode->boot_size);
- IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
+ /* api_ver should match the api version forming part of the
+ * firmware filename ... but we don't check for that and only rely
+ * on the API version read from firware header from here on forward */
+
+ if (api_ver < api_min || api_ver > api_max) {
+ IWL_ERROR("Driver unable to support your firmware API. "
+ "Driver supports v%u, firmware is v%u.\n",
+ api_max, api_ver);
+ priv->ucode_ver = 0;
+ ret = -EINVAL;
+ goto err_release;
+ }
+ if (api_ver != api_max)
+ IWL_ERROR("Firmware has old API version. Expected %u, "
+ "got %u. New firmware can be obtained "
+ "from http://www.intellinuxwireless.org.\n",
+ api_max, api_ver);
+
+ printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
+ IWL_UCODE_MAJOR(priv->ucode_ver),
+ IWL_UCODE_MINOR(priv->ucode_ver),
+ IWL_UCODE_API(priv->ucode_ver),
+ IWL_UCODE_SERIAL(priv->ucode_ver));
+ IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
+ priv->ucode_ver);
IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
+
/* Verify size of file vs. image size info in file's header */
if (ucode_raw->size < sizeof(*ucode) +
inst_size + data_size + init_size +
@@ -5607,7 +5567,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
priv->ucode_data.len);
- /* Inst bytecount must be last to set up, bit 31 signals uCode
+ /* Inst byte count must be last to set up, bit 31 signals uCode
* that all new ptr/size info is in place */
iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -5665,6 +5625,10 @@ static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
}
+/* temporary */
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb);
+
/**
* iwl3945_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -5699,7 +5663,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
rc = iwl3945_grab_nic_access(priv);
if (rc) {
- IWL_WARNING("Can not read rfkill status from adapter\n");
+ IWL_WARNING("Can not read RFKILL status from adapter\n");
return;
}
@@ -5709,7 +5673,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
if (rfkill & 0x1) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- /* if rfkill is not on, then wait for thermal
+ /* if RFKILL is not on, then wait for thermal
* sensor in adapter to kick in */
while (iwl3945_hw_get_temperature(priv) == 0) {
thermal_spin++;
@@ -5747,7 +5711,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl3945_connection_init_rx_config(priv);
+ iwl3945_connection_init_rx_config(priv, priv->iw_mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
}
@@ -5768,6 +5732,14 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
if (priv->error_recovering)
iwl3945_error_recovery(priv);
+ /* 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)
+ iwl3945_mac_beacon_update(priv->hw, beacon);
+ }
+
return;
restart:
@@ -5902,7 +5874,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
}
if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
- IWL_ERROR("ucode not available for device bringup\n");
+ IWL_ERROR("ucode not available for device bring up\n");
return -EIO;
}
@@ -6046,24 +6018,6 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
iwl3945_rfkill_set_hw_state(priv);
}
-static void iwl3945_bg_set_monitor(struct work_struct *work)
-{
- struct iwl3945_priv *priv = container_of(work,
- struct iwl3945_priv, set_monitor);
-
- IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
-
- mutex_lock(&priv->mutex);
-
- if (!iwl3945_is_ready(priv))
- IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
- else
- if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0)
- IWL_ERROR("iwl3945_set_mode() failed\n");
-
- mutex_unlock(&priv->mutex);
-}
-
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
static void iwl3945_bg_scan_check(struct work_struct *data)
@@ -6101,6 +6055,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
struct ieee80211_conf *conf = NULL;
u8 n_probes = 2;
enum ieee80211_band band;
+ DECLARE_SSID_BUF(ssid);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -6111,7 +6066,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
goto done;
}
- /* Make sure the scan wasn't cancelled before this queued work
+ /* Make sure the scan wasn't canceled before this queued work
* was given the chance to run... */
if (!test_bit(STATUS_SCANNING, &priv->status))
goto done;
@@ -6201,21 +6156,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
if (priv->one_direct_scan) {
IWL_DEBUG_SCAN
("Kicking off one direct scan for '%s'\n",
- iwl3945_escape_essid(priv->direct_ssid,
- priv->direct_ssid_len));
+ print_ssid(ssid, priv->direct_ssid,
+ priv->direct_ssid_len));
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
n_probes++;
- } else if (!iwl3945_is_associated(priv) && priv->essid_len) {
- IWL_DEBUG_SCAN
- ("Kicking off one direct scan for '%s' when not associated\n",
- iwl3945_escape_essid(priv->essid, priv->essid_len));
- scan->direct_scan[0].id = WLAN_EID_SSID;
- scan->direct_scan[0].len = priv->essid_len;
- memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- n_probes++;
} else
IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
@@ -6223,7 +6170,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.len = cpu_to_le16(
iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
- IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+ IWL_MAX_SCAN_SIZE - sizeof(*scan)));
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -6333,7 +6280,6 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
- DECLARE_MAC_BUF(mac);
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
@@ -6341,9 +6287,8 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
}
- IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
- priv->assoc_id,
- print_mac(mac, priv->active_rxon.bssid_addr));
+ IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+ priv->assoc_id, priv->active_rxon.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -6398,10 +6343,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
case NL80211_IFTYPE_ADHOC:
- /* clear out the station table */
- iwl3945_clear_stations_table(priv);
-
- iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+ priv->assoc_id = 1;
iwl3945_add_station(priv, priv->bssid, 0, 0);
iwl3945_sync_sta(priv, IWL_STA_ID,
(priv->band == IEEE80211_BAND_5GHZ) ?
@@ -6439,7 +6381,7 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
static void iwl3945_bg_scan_completed(struct work_struct *work)
{
@@ -6452,7 +6394,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
return;
if (test_bit(STATUS_CONF_PENDING, &priv->status))
- iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+ iwl3945_mac_config(priv->hw, 0);
ieee80211_scan_completed(priv->hw);
@@ -6604,7 +6546,6 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
{
struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
@@ -6615,13 +6556,14 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
spin_lock_irqsave(&priv->lock, flags);
priv->vif = conf->vif;
+ priv->iw_mode = conf->type;
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
if (conf->mac_addr) {
- IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr));
+ IWL_DEBUG_MAC80211("Set: %pM\n", conf->mac_addr);
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
@@ -6641,10 +6583,11 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
* be set inappropriately and the driver currently sets the hardware up to
* use it whenever needed.
*/
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct iwl3945_priv *priv = hw->priv;
const struct iwl3945_channel_info *ch_info;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
int ret = 0;
@@ -6782,16 +6725,11 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
* clear sta table, add BCAST sta... */
}
-/* temporary */
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
-
static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct iwl3945_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
- unsigned long flags;
int rc;
if (conf == NULL)
@@ -6808,28 +6746,20 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
return -ENOMEM;
+ mutex_lock(&priv->mutex);
rc = iwl3945_mac_beacon_update(hw, beacon);
+ mutex_unlock(&priv->mutex);
if (rc)
return rc;
}
- /* XXX: this MUST use conf->mac_addr */
-
- if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
- (!conf->ssid_len)) {
- IWL_DEBUG_MAC80211
- ("Leaving in AP mode because HostAPD is not ready.\n");
- return 0;
- }
-
if (!iwl3945_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
if (conf->bssid)
- IWL_DEBUG_MAC80211("bssid: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
/*
* very dubious code was here; the probe filtering flag is never set:
@@ -6842,8 +6772,8 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
- IWL_DEBUG_MAC80211("bssid was set to: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+ conf->bssid);
}
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
@@ -6889,15 +6819,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
}
done:
- spin_lock_irqsave(&priv->lock, flags);
- if (!conf->ssid_len)
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- else
- memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
- priv->essid_len = conf->ssid_len;
- spin_unlock_irqrestore(&priv->lock, flags);
-
IWL_DEBUG_MAC80211("leave\n");
mutex_unlock(&priv->mutex);
@@ -6910,16 +6831,43 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
int mc_count, struct dev_addr_list *mc_list)
{
struct iwl3945_priv *priv = hw->priv;
+ __le32 *filter_flags = &priv->staging_rxon.filter_flags;
- if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- NL80211_IFTYPE_MONITOR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
+ IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
+ changed_flags, *total_flags);
+
+ if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+ if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
+ *filter_flags |= RXON_FILTER_PROMISC_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_PROMISC_MSK;
}
- *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ if (changed_flags & FIF_ALLMULTI) {
+ if (*total_flags & FIF_ALLMULTI)
+ *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
+ }
+ if (changed_flags & FIF_CONTROL) {
+ if (*total_flags & FIF_CONTROL)
+ *filter_flags |= RXON_FILTER_CTL2HOST_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
+ }
+ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+ *filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
+ }
+
+ /* We avoid iwl_commit_rxon here to commit the new filter flags
+ * since mac80211 will call ieee80211_hw_config immediately.
+ * (mc_list is not supported at this time). Otherwise, we need to
+ * queue a background iwl_commit_rxon work.
+ */
+
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
@@ -6940,8 +6888,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
if (priv->vif == conf->vif) {
priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- priv->essid_len = 0;
}
mutex_unlock(&priv->mutex);
@@ -7010,6 +6956,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
int rc = 0;
unsigned long flags;
struct iwl3945_priv *priv = hw->priv;
+ DECLARE_SSID_BUF(ssid_buf);
IWL_DEBUG_MAC80211("enter\n");
@@ -7022,12 +6969,6 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
- if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
- rc = -EIO;
- IWL_ERROR("ERROR: APs don't scan\n");
- goto out_unlock;
- }
-
/* we don't schedule scan within next_scan_jiffies period */
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
@@ -7043,7 +6984,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
}
if (len) {
IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
- iwl3945_escape_essid(ssid, len), (int)len);
+ print_ssid(ssid_buf, ssid, len), (int)len);
priv->one_direct_scan = 1;
priv->direct_ssid_len = (u8)
@@ -7084,10 +7025,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
sta_id = iwl3945_hw_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
+ IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+ addr);
return -EINVAL;
}
@@ -7143,11 +7082,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
- if (!priv->qos_data.qos_enable) {
- priv->qos_data.qos_active = 0;
- IWL_DEBUG_MAC80211("leave - qos not enabled\n");
- return 0;
- }
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags);
@@ -7219,14 +7153,6 @@ static int iwl3945_mac_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 iwl3945_mac_get_tsf(struct ieee80211_hw *hw)
-{
- IWL_DEBUG_MAC80211("enter\n");
- IWL_DEBUG_MAC80211("leave\n");
-
- return 0;
-}
-
static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl3945_priv *priv = hw->priv;
@@ -7292,18 +7218,15 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
- mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
@@ -7323,7 +7246,6 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
iwl3945_post_associate(priv);
- mutex_unlock(&priv->mutex);
return 0;
}
@@ -7792,7 +7714,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
/*****************************************************************************
*
- * driver setup and teardown
+ * driver setup and tear down
*
*****************************************************************************/
@@ -7810,7 +7732,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
- INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor);
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->scan_check, iwl3945_bg_scan_check);
@@ -7869,7 +7790,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.get_stats = iwl3945_mac_get_stats,
.get_tx_stats = iwl3945_mac_get_tx_stats,
.conf_tx = iwl3945_mac_conf_tx,
- .get_tsf = iwl3945_mac_get_tsf,
.reset_tsf = iwl3945_mac_reset_tsf,
.bss_info_changed = iwl3945_bss_info_changed,
.hw_scan = iwl3945_mac_hw_scan
@@ -7882,7 +7802,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
struct ieee80211_hw *hw;
struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
unsigned long flags;
- DECLARE_MAC_BUF(mac);
+
+ /***********************
+ * 1. Allocating HW data
+ * ********************/
/* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan. */
@@ -7907,48 +7830,41 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
err = -ENOMEM;
goto out;
}
- SET_IEEE80211_DEV(hw, &pdev->dev);
- hw->rate_control_algorithm = "iwl-3945-rs";
- hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+ SET_IEEE80211_DEV(hw, &pdev->dev);
- IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
-
priv->pci_dev = pdev;
priv->cfg = cfg;
+ IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
+ hw->rate_control_algorithm = "iwl-3945-rs";
+ hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+
/* Select antenna (may be helpful if only one antenna is connected) */
priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
#ifdef CONFIG_IWL3945_DEBUG
iwl3945_debug_level = iwl3945_param_debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
- priv->retry_rate = 1;
-
- priv->ibss_beacon = NULL;
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
+ hw->wiphy->fw_handles_regulatory = true;
+
/* 4 EDCA QOS priorities */
hw->queues = 4;
- spin_lock_init(&priv->lock);
- spin_lock_init(&priv->power_data.lock);
- spin_lock_init(&priv->sta_lock);
- spin_lock_init(&priv->hcmd_lock);
-
- INIT_LIST_HEAD(&priv->free_frames);
-
- mutex_init(&priv->mutex);
+ /***************************
+ * 2. Initializing PCI bus
+ * *************************/
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_ieee80211_free_hw;
@@ -7956,14 +7872,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_set_master(pdev);
- /* Clear the driver's (not device's) station table */
- iwl3945_clear_stations_table(priv);
-
- priv->data_retry_limit = -1;
- priv->ieee_channels = NULL;
- priv->ieee_rates = NULL;
- priv->band = IEEE80211_BAND_2GHZ;
-
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (!err)
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
@@ -7977,10 +7885,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (err)
goto out_pci_disable_device;
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, 0x41, 0x00);
-
+ /***********************
+ * 3. Read REV Register
+ * ********************/
priv->hw_base = pci_iomap(pdev, 0, 0);
if (!priv->hw_base) {
err = -ENODEV;
@@ -7991,97 +7898,144 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
(unsigned long long) pci_resource_len(pdev, 0));
IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
- /* Initialize module parameter values here */
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, 0x41, 0x00);
- /* Disable radio (SW RF KILL) via parameter when loading driver */
- if (iwl3945_param_disable) {
- set_bit(STATUS_RF_KILL_SW, &priv->status);
- IWL_DEBUG_INFO("Radio disabled.\n");
- }
+ /* nic init */
+ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
- priv->iw_mode = NL80211_IFTYPE_STATION;
+ iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ err = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ goto out_remove_sysfs;
+ }
- printk(KERN_INFO DRV_NAME
- ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+ /***********************
+ * 4. Read EEPROM
+ * ********************/
+ /* Read the EEPROM */
+ err = iwl3945_eeprom_init(priv);
+ if (err) {
+ IWL_ERROR("Unable to init EEPROM\n");
+ goto out_remove_sysfs;
+ }
+ /* MAC Address location in EEPROM same for 3945/4965 */
+ get_eeprom_mac(priv, priv->mac_addr);
+ IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ /***********************
+ * 5. Setup HW Constants
+ * ********************/
/* Device-specific setup */
if (iwl3945_hw_set_hw_setting(priv)) {
IWL_ERROR("failed to set hw settings\n");
goto out_iounmap;
}
- if (iwl3945_param_qos_enable)
- priv->qos_data.qos_enable = 1;
+ /***********************
+ * 6. Setup priv
+ * ********************/
+ priv->retry_rate = 1;
+ priv->ibss_beacon = NULL;
+
+ spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->power_data.lock);
+ spin_lock_init(&priv->sta_lock);
+ spin_lock_init(&priv->hcmd_lock);
+
+ INIT_LIST_HEAD(&priv->free_frames);
+ mutex_init(&priv->mutex);
+
+ /* Clear the driver's (not device's) station table */
+ iwl3945_clear_stations_table(priv);
+
+ priv->data_retry_limit = -1;
+ priv->ieee_channels = NULL;
+ priv->ieee_rates = NULL;
+ priv->band = IEEE80211_BAND_2GHZ;
+
+ priv->iw_mode = NL80211_IFTYPE_STATION;
iwl3945_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
- iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
- iwl3945_setup_deferred_work(priv);
- iwl3945_setup_rx_handlers(priv);
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
- spin_lock_irqsave(&priv->lock, flags);
- iwl3945_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ err = iwl3945_init_channel_map(priv);
if (err) {
- IWL_ERROR("failed to create sysfs device attributes\n");
+ IWL_ERROR("initializing regulatory failed: %d\n", err);
goto out_release_irq;
}
- /* nic init */
- iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
- CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
- iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
- if (err < 0) {
- IWL_DEBUG_INFO("Failed to init the card\n");
- goto out_remove_sysfs;
- }
- /* Read the EEPROM */
- err = iwl3945_eeprom_init(priv);
+ err = iwl3945_init_geos(priv);
if (err) {
- IWL_ERROR("Unable to init EEPROM\n");
- goto out_remove_sysfs;
+ IWL_ERROR("initializing geos failed: %d\n", err);
+ goto out_free_channel_map;
}
- /* MAC Address location in EEPROM same for 3945/4965 */
- get_eeprom_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
- err = iwl3945_init_channel_map(priv);
- if (err) {
- IWL_ERROR("initializing regulatory failed: %d\n", err);
- goto out_remove_sysfs;
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+
+ /***********************************
+ * 7. Initialize Module Parameters
+ * **********************************/
+
+ /* Initialize module parameter values here */
+ /* Disable radio (SW RF KILL) via parameter when loading driver */
+ if (iwl3945_param_disable) {
+ set_bit(STATUS_RF_KILL_SW, &priv->status);
+ IWL_DEBUG_INFO("Radio disabled.\n");
}
- err = iwl3945_init_geos(priv);
+
+ /***********************
+ * 8. Setup Services
+ * ********************/
+
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl3945_disable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
if (err) {
- IWL_ERROR("initializing geos failed: %d\n", err);
- goto out_free_channel_map;
+ IWL_ERROR("failed to create sysfs device attributes\n");
+ goto out_free_geos;
}
+ iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
+ iwl3945_setup_deferred_work(priv);
+ iwl3945_setup_rx_handlers(priv);
+
+ /***********************
+ * 9. Conclude
+ * ********************/
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ /*********************************
+ * 10. Setup and Register mac80211
+ * *******************************/
+
err = ieee80211_register_hw(priv->hw);
if (err) {
IWL_ERROR("Failed to register network device (error %d)\n", err);
- goto out_free_geos;
+ goto out_remove_sysfs;
}
priv->hw->conf.beacon_int = 100;
priv->mac80211_registered = 1;
- pci_save_state(pdev);
- pci_disable_device(pdev);
+
err = iwl3945_rfkill_init(priv);
if (err)
@@ -8090,12 +8044,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return 0;
+ out_remove_sysfs:
+ sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
out_free_geos:
iwl3945_free_geos(priv);
out_free_channel_map:
iwl3945_free_channel_map(priv);
- out_remove_sysfs:
- sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+
out_release_irq:
destroy_workqueue(priv->workqueue);
@@ -8222,7 +8177,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
- IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+ IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
mutex_lock(&priv->mutex);
switch (state) {
@@ -8237,7 +8192,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
iwl3945_radio_kill_sw(priv, 1);
break;
default:
- IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+ IWL_WARNING("we received unexpected RFKILL state %d\n", state);
break;
}
out_unlock:
@@ -8379,7 +8334,7 @@ static void __exit iwl3945_exit(void)
iwl3945_rate_control_unregister();
}
-MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode");
+MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
module_param_named(antenna, iwl3945_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
@@ -8388,7 +8343,7 @@ MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444);
MODULE_PARM_DESC(hwcrypto,
"using hardware crypto engine (default 0 [software])\n");
-module_param_named(debug, iwl3945_param_debug, int, 0444);
+module_param_named(debug, iwl3945_param_debug, uint, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
@@ -8396,9 +8351,5 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
module_param_named(queues_num, iwl3945_param_queues_num, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
-/* QoS */
-module_param_named(qos_enable, iwl3945_param_qos_enable, int, 0444);
-MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
-
module_exit(iwl3945_exit);
module_init(iwl3945_init);