#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <asm/div64.h>
+#define IWL 4965
+
#include "iwlwifi.h"
#include "iwl-4965.h"
#include "iwl-helpers.h"
#define VS
#endif
-#define IWLWIFI_VERSION "0.1.15k" VD VS
+#define IWLWIFI_VERSION "1.1.17k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
#define DRV_VERSION IWLWIFI_VERSION
* reclaiming packets (on 'tx done IRQ), if free space become > high mark,
* Tx queue resumed.
*
- * The IPW operates with six queues, one receive queue in the device's
+ * The IWL operates with six queues, one receive queue in the device's
* sram, one transmit queue for sending commands to the device firmware,
* and four transmit queues for data.
***************************************************/
/**************************************************************/
+#if 0 /* temparary disable till we add real remove station */
static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
{
int index = IWL_INVALID_STATION;
spin_unlock_irqrestore(&priv->sta_lock, flags);
return 0;
}
+#endif
static void iwl_clear_stations_table(struct iwl_priv *priv)
{
int index = IWL_INVALID_STATION;
struct iwl_station_entry *station;
unsigned long flags_spin;
+ DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
}
- IWL_DEBUG_ASSOC("Add STA ID %d: " MAC_FMT "\n", index, MAC_ARG(addr));
+ IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
station = &priv->stations[index];
station->used = 1;
priv->num_stations++;
static int iwl_rxon_add_station(struct iwl_priv *priv,
const u8 *addr, int is_ap)
{
- u8 rc;
-
- /* Remove this station if it happens to already exist */
- iwl_remove_station(priv, addr, is_ap);
-
- rc = iwl_add_station(priv, addr, is_ap, 0);
+ u8 sta_id;
+ sta_id = iwl_add_station(priv, addr, is_ap, 0);
iwl4965_add_station(priv, addr, is_ap);
- return rc;
+ return sta_id;
}
/**
{
/* cast away the const for active_rxon in this function */
struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ DECLARE_MAC_BUF(mac);
int rc = 0;
if (!iwl_is_alive(priv))
"configuration (%d).\n", rc);
return rc;
}
-
- /* The RXON bit toggling will have cleared out the
- * station table in the uCode, so blank it in the driver
- * as well */
- iwl_clear_stations_table(priv);
- } else if (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) {
- /* When switching from non-associated to associated, the
- * uCode clears out the station table; so clear it in the
- * driver as well */
- iwl_clear_stations_table(priv);
}
IWL_DEBUG_INFO("Sending RXON\n"
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
- "* bssid = " MAC_FMT "\n",
+ "* bssid = %s\n",
((priv->staging_rxon.filter_flags &
RXON_FILTER_ASSOC_MSK) ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
- MAC_ARG(priv->staging_rxon.bssid_addr));
+ print_mac(mac, priv->staging_rxon.bssid_addr));
/* Apply the new configuration */
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
return rc;
}
+ iwl_clear_stations_table(priv);
+
#ifdef CONFIG_IWLWIFI_SENSITIVITY
if (!priv->error_recovering)
priv->start_calib = 0;
* return : set the bit for each supported rate insert in ie
*/
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
- u16 basic_rate, int max_count)
+ u16 basic_rate, int *left)
{
u16 ret_rates = 0, bit;
int i;
- u8 *rates;
-
- rates = &(ie[1]);
+ u8 *cnt = ie;
+ u8 *rates = ie + 1;
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*ie] = iwl_rates[i].ieee |
- ((bit & basic_rate) ? 0x80 : 0x00);
- *ie = *ie + 1;
- if (*ie >= max_count)
+ rates[*cnt] = iwl_rates[i].ieee |
+ ((bit & basic_rate) ? 0x80 : 0x00);
+ (*cnt)++;
+ (*left)--;
+ if ((*left <= 0) ||
+ (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
break;
}
}
{
int len = 0;
u8 *pos = NULL;
- u16 ret_rates;
+ u16 active_rates, ret_rates, cck_rates;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
left -= 2;
if (left < 0)
return 0;
+
/* ... fill it in... */
*pos++ = WLAN_EID_SUPP_RATES;
*pos = 0;
- ret_rates = priv->active_rate = priv->rates_mask;
+
+ priv->active_rate = priv->rates_mask;
+ active_rates = priv->active_rate;
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
- iwl_supported_rate_to_ie(pos, priv->active_rate,
- priv->active_rate_basic, left);
+ cck_rates = IWL_CCK_RATES_MASK & active_rates;
+ ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
+ ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
+ active_rates &= ~ret_rates;
+
len += 2 + *pos;
pos += (*pos) + 1;
- ret_rates = ~ret_rates & priv->active_rate;
-
- if (ret_rates == 0)
+ if (active_rates == 0)
goto fill_end;
/* fill in supported extended rate */
/* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0;
- iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
+ iwl_supported_rate_to_ie(pos, active_rates,
+ priv->active_rate_basic, &left);
if (*pos > 0)
len += 2 + *pos;
"with key %d\n", ctl->key_idx);
break;
- case ALG_NONE:
- IWL_DEBUG_TX("Tx packet in the clear (encrypt requested).\n");
- break;
-
default:
printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg);
break;
{
int sta_id;
u16 fc = le16_to_cpu(hdr->frame_control);
+ DECLARE_MAC_BUF(mac);
/* If this frame is broadcast or not data then use the broadcast
* station id */
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- IWL_DEBUG_DROP("Station " MAC_FMT " not in station map. "
+ IWL_DEBUG_DROP("Station %s not in station map. "
"Defaulting to broadcast...\n",
- MAC_ARG(hdr->addr1));
+ print_mac(mac, hdr->addr1));
iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
hdr_len = ieee80211_get_hdrlen(fc);
sta_id = iwl_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_DROP("Dropping - INVALID STATION: " MAC_FMT "\n",
- MAC_ARG(hdr->addr1));
+ DECLARE_MAC_BUF(mac);
+
+ IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
+ print_mac(mac, hdr->addr1));
goto drop;
}
* Conversion assumes that levels are voltages (20*log), not powers (10*log). */
int iwl_calc_db_from_ratio(int sig_ratio)
{
- /* Anything above 1000:1 just report as 60 dB */
- if (sig_ratio > 1000)
+ /* 1000:1 or higher just report as 60 dB */
+ if (sig_ratio >= 1000)
return 60;
- /* Above 100:1, divide by 10 and use table,
+ /* 100:1 or higher, divide by 10 and use table,
* add 20 dB to make up for divide by 10 */
- if (sig_ratio > 100)
+ if (sig_ratio >= 100)
return (20 + (int)ratio2dB[sig_ratio/10]);
/* We shouldn't see this */
reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
(pkt->hdr.cmd != REPLY_4965_RX) &&
+ (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
(pkt->hdr.cmd != REPLY_TX);
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
{
+ DECLARE_MAC_BUF(mac);
+
IWL_DEBUG_RADIO("RX CONFIG:\n");
iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
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: " MAC_FMT "\n",
- MAC_ARG(rxon->node_addr));
- IWL_DEBUG_RADIO("u8[6] bssid_addr: " MAC_FMT "\n",
- MAC_ARG(rxon->bssid_addr));
+ 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("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif
/* bail out if nothing in log */
if (size == 0) {
- IWL_ERROR("Start IPW Event Log Dump: nothing in log\n");
+ IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
iwl_release_restricted_access(priv);
return;
}
- IWL_ERROR("Start IPW Event Log Dump: display count %d, wraps %d\n",
+ IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
size, num_wraps);
/* if uCode has wrapped back to top of log, start at the oldest entry,
}
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
- /* Hardware disappeared */
+ /* Hardware disappeared. It might have already raised
+ * an interrupt */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
- spin_unlock(&priv->lock);
+ unplugged:
+ spin_unlock(&priv->lock);
return IRQ_HANDLED;
none:
static int __iwl_up(struct iwl_priv *priv)
{
+ DECLARE_MAC_BUF(mac);
int rc, i;
u32 hw_rf_kill = 0;
/* MAC Address location in EEPROM same for 3945/4965 */
get_eeprom_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: " MAC_FMT "\n",
- MAC_ARG(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);
IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
"Scan completion watchdog resetting adapter (%dms)\n",
jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
+ iwl_send_scan_abort(priv);
}
mutex_unlock(&priv->mutex);
}
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
- scan->max_out_time = cpu_to_le32(600 * 1024);
+ scan->max_out_time = cpu_to_le32(200 * 1024);
if (!interval)
interval = suspend_time;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
direct_mask = 1;
- } else if (!iwl_is_associated(priv)) {
+ } else if (!iwl_is_associated(priv) && 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);
int rc = 0;
struct ieee80211_conf *conf = NULL;
+ DECLARE_MAC_BUF(mac);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
return;
}
- IWL_DEBUG_ASSOC("Associated as %d to: " MAC_FMT "\n",
- priv->assoc_id, MAC_ARG(priv->active_rxon.bssid_addr));
+ IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
+ priv->assoc_id,
+ print_mac(mac, priv->active_rxon.bssid_addr));
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
mutex_lock(&priv->mutex);
+ if (!priv->interface_id || !priv->is_open) {
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+ iwl_scan_cancel_timeout(priv, 200);
+
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
*
*****************************************************************************/
-static int iwl_mac_open(struct ieee80211_hw *hw)
+static int iwl_mac_start(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
return 0;
}
-static int iwl_mac_stop(struct ieee80211_hw *hw)
+static void iwl_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
+
+
+ mutex_lock(&priv->mutex);
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
priv->is_open = 0;
- /*netif_stop_queue(dev); */
- flush_workqueue(priv->workqueue);
- IWL_DEBUG_MAC80211("leave\n");
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ mutex_unlock(&priv->mutex);
- return 0;
+ IWL_DEBUG_MAC80211("leave\n");
}
static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
+ DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
if (conf->mac_addr)
- IWL_DEBUG_MAC80211("enter: MAC " MAC_FMT "\n",
- MAC_ARG(conf->mac_addr));
+ IWL_DEBUG_MAC80211("enter: MAC %s\n",
+ print_mac(mac, conf->mac_addr));
if (priv->interface_id) {
IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
iwl_activate_qos(priv, 1);
#endif
iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
- iwl_send_beacon_cmd(priv);
- } else
- iwl_send_beacon_cmd(priv);
+ }
+ iwl_send_beacon_cmd(priv);
/* FIXME - we need to add code here to detect a totally new
* configuration, reset the AP, unassoc, rxon timing, assoc,
struct ieee80211_if_conf *conf)
{
struct iwl_priv *priv = hw->priv;
+ DECLARE_MAC_BUF(mac);
unsigned long flags;
int rc;
IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
if (conf->bssid)
- IWL_DEBUG_MAC80211("bssid: " MAC_FMT "\n",
- MAC_ARG(conf->bssid));
+ IWL_DEBUG_MAC80211("bssid: %s\n",
+ print_mac(mac, conf->bssid));
+/*
+ * very dubious code was here; the probe filtering flag is never set:
+ *
if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
!(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
+ */
+ if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211("leave - scanning\n");
mutex_unlock(&priv->mutex);
return 0;
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
- IWL_DEBUG_MAC80211("bssid was set to: " MAC_FMT "\n",
- MAC_ARG(conf->bssid));
+ IWL_DEBUG_MAC80211("bssid was set to: %s\n",
+ print_mac(mac, conf->bssid));
}
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
iwl_config_ap(priv);
else {
- priv->staging_rxon.filter_flags |=
- RXON_FILTER_ASSOC_MSK;
rc = iwl_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
iwl_rxon_add_station(
}
} else {
+ iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl_commit_rxon(priv);
}
return 0;
}
+static void iwl_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count, struct dev_addr_list *mc_list)
+{
+ /*
+ * XXX: dummy
+ * see also iwl_connection_init_rx_config
+ */
+ *total_flags = 0;
+}
+
static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
+
+ iwl_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+
if (priv->interface_id == conf->if_id) {
priv->interface_id = 0;
memset(priv->bssid, 0, ETH_ALEN);
IWL_DEBUG_MAC80211("enter\n");
+ mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
priv->direct_ssid_len = (u8)
min((u8) len, (u8) IW_ESSID_MAX_SIZE);
memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
- }
+ } else
+ priv->one_direct_scan = 0;
rc = iwl_scan_initiate(priv);
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
+ mutex_unlock(&priv->mutex);
return rc;
}
-static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd,
+static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
struct iwl_priv *priv = hw->priv;
+ DECLARE_MAC_BUF(mac);
int rc = 0;
u8 sta_id;
sta_id = iwl_hw_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211("leave - " MAC_FMT " not in station map.\n",
- MAC_ARG(addr));
+ IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
+ print_mac(mac, addr));
return -EINVAL;
}
mutex_lock(&priv->mutex);
+ iwl_scan_cancel_timeout(priv, 100);
+
switch (cmd) {
case SET_KEY:
rc = iwl_update_sta_key_info(priv, key, sta_id);
spin_unlock_irqrestore(&priv->lock, flags);
+ /* we are restarting association process
+ * clear RXON_FILTER_ASSOC_MSK bit
+ */
+ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ iwl_scan_cancel_timeout(priv, 100);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl_commit_rxon(priv);
+ }
+
/* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
+
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
return;
static struct ieee80211_ops iwl_hw_ops = {
.tx = iwl_mac_tx,
- .open = iwl_mac_open,
+ .start = iwl_mac_start,
.stop = iwl_mac_stop,
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
.config = iwl_mac_config,
.config_interface = iwl_mac_config_interface,
+ .configure_filter = iwl_configure_filter,
.set_key = iwl_mac_set_key,
.get_stats = iwl_mac_get_stats,
.get_tx_stats = iwl_mac_get_tx_stats,
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-4965-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
iwl_rate_control_unregister(priv->hw);
}
+ /*netif_stop_queue(dev); */
+ flush_workqueue(priv->workqueue);
+
/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */