]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/iwlwifi/iwl4965-base.c
iwlwifi: don't bring up interface if RF-kill avoids radio
[linux-2.6] / drivers / net / wireless / iwlwifi / iwl4965-base.c
index 81a1c22874a1ab2785ec29d153a00a8ff3d9b8f7..2d0d079a24ec7ad68b0e3168cb212144ead76af7 100644 (file)
@@ -192,7 +192,7 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv)
 {
 
        /* These items are only settable from the full RXON command */
-       if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
+       if (!(iwl_is_associated(priv)) ||
            compare_ether_addr(priv->staging_rxon.bssid_addr,
                               priv->active_rxon.bssid_addr) ||
            compare_ether_addr(priv->staging_rxon.node_addr,
@@ -241,16 +241,18 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
        /* 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;
+       int ret;
+       bool new_assoc =
+               !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
 
        if (!iwl_is_alive(priv))
-               return -1;
+               return -EBUSY;
 
        /* always get timestamp with Rx frame */
        priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
 
-       rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
-       if (rc) {
+       ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
+       if (ret) {
                IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
                return -EINVAL;
        }
@@ -259,15 +261,13 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
         * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
         * and other flags for the current radio configuration. */
        if (!iwl4965_full_rxon_required(priv)) {
-               rc = iwl_send_rxon_assoc(priv);
-               if (rc) {
-                       IWL_ERROR("Error setting RXON_ASSOC "
-                                 "configuration (%d).\n", rc);
-                       return rc;
+               ret = iwl_send_rxon_assoc(priv);
+               if (ret) {
+                       IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
+                       return ret;
                }
 
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
                return 0;
        }
 
@@ -278,22 +278,20 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
         * an RXON_ASSOC and the new config wants the associated mask enabled,
         * we must clear the associated from the active configuration
         * before we apply the new config */
-       if (iwl_is_associated(priv) &&
-           (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+       if (iwl_is_associated(priv) && new_assoc) {
                IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
-               rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+               ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
                                      sizeof(struct iwl_rxon_cmd),
                                      &priv->active_rxon);
 
                /* If the mask clearing failed then we set
                 * active_rxon back to what it was previously */
-               if (rc) {
+               if (ret) {
                        active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-                       IWL_ERROR("Error clearing ASSOC_MSK on current "
-                                 "configuration (%d).\n", rc);
-                       return rc;
+                       IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret);
+                       return ret;
                }
        }
 
@@ -301,58 +299,75 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
                       "* with%s RXON_FILTER_ASSOC_MSK\n"
                       "* channel = %d\n"
                       "* bssid = %s\n",
-                      ((priv->staging_rxon.filter_flags &
-                        RXON_FILTER_ASSOC_MSK) ? "" : "out"),
+                      (new_assoc ? "" : "out"),
                       le16_to_cpu(priv->staging_rxon.channel),
                       print_mac(mac, priv->staging_rxon.bssid_addr));
 
        iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
-       /* Apply the new configuration */
-       rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+
+       /* Apply the new configuration
+        * RXON unassoc clears the station table in uCode, send it before
+        * we add the bcast station. If assoc bit is set, we will send RXON
+        * after having added the bcast and bssid station.
+        */
+       if (!new_assoc) {
+               ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
                              sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
-       if (rc) {
-               IWL_ERROR("Error setting new configuration (%d).\n", rc);
-               return rc;
+               if (ret) {
+                       IWL_ERROR("Error setting new RXON (%d)\n", ret);
+                       return ret;
+               }
+               memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
        }
 
-       iwl_remove_station(priv, iwl_bcast_addr, 0);
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        if (!priv->error_recovering)
                priv->start_calib = 0;
 
        iwl_init_sensitivity(priv);
 
-       memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
        /* If we issue a new RXON command which required a tune then we must
         * send a new TXPOWER command or we won't be able to Tx any frames */
-       rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-       if (rc) {
-               IWL_ERROR("Error sending TX power (%d).\n", rc);
-               return rc;
+       ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+       if (ret) {
+               IWL_ERROR("Error sending TX power (%d)\n", ret);
+               return ret;
        }
 
        /* Add the broadcast address so we can send broadcast frames */
        if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
-           IWL_INVALID_STATION) {
+                                               IWL_INVALID_STATION) {
                IWL_ERROR("Error adding BROADCAST address for transmit.\n");
                return -EIO;
        }
 
        /* If we have set the ASSOC_MSK and we are in BSS mode then
         * add the IWL_AP_ID to the station rate table */
-       if (iwl_is_associated(priv) &&
-           (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
-               if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
-                   == IWL_INVALID_STATION) {
-                       IWL_ERROR("Error adding AP address for transmit.\n");
-                       return -EIO;
+       if (new_assoc) {
+               if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+                       ret = iwl_rxon_add_station(priv,
+                                          priv->active_rxon.bssid_addr, 1);
+                       if (ret == IWL_INVALID_STATION) {
+                               IWL_ERROR("Error adding AP address for TX.\n");
+                               return -EIO;
+                       }
+                       priv->assoc_station_added = 1;
+                       if (priv->default_wep_key &&
+                           iwl_send_static_wepkey_cmd(priv, 0))
+                               IWL_ERROR("Could not send WEP static key.\n");
                }
-               priv->assoc_station_added = 1;
-               if (priv->default_wep_key &&
-                   iwl_send_static_wepkey_cmd(priv, 0))
-                       IWL_ERROR("Could not send WEP static key.\n");
+
+               /* Apply the new configuration
+                * RXON assoc doesn't clear the station table in uCode,
+                */
+               ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
+                             sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+               if (ret) {
+                       IWL_ERROR("Error setting new RXON (%d)\n", ret);
+                       return ret;
+               }
+               memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
        }
 
        return 0;
@@ -379,28 +394,6 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv)
                                sizeof(struct iwl4965_bt_cmd), &bt_cmd);
 }
 
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_CARD_STATE_CMD,
-               .len = sizeof(u32),
-               .data = &flags,
-               .meta.flags = meta_flag,
-       };
-
-       return iwl_send_cmd(priv, &cmd);
-}
-
 static void iwl_clear_free_frames(struct iwl_priv *priv)
 {
        struct list_head *element;
@@ -623,50 +616,6 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
        }
 }
 
-int iwl4965_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 IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr2, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our IBSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr3, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr3, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our BSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr2, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       default:
-               break;
-       }
-
-       return 1;
-}
-
-static void iwl4965_sequence_reset(struct iwl_priv *priv)
-{
-       /* Reset ieee stats */
-
-       /* We don't reset the net_device_stats (ieee->stats) on
-        * re-association */
-
-       priv->last_seq_num = -1;
-       priv->last_frag_num = -1;
-       priv->last_packet_time = 0;
-
-       iwl_scan_cancel(priv);
-}
-
 #define MAX_UCODE_BEACON_INTERVAL      4096
 #define INTEL_CONN_LISTEN_INTERVAL     __constant_cpu_to_le16(0xA)
 
@@ -851,7 +800,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
        iwl4965_connection_init_rx_config(priv);
        memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        /* dont commit rxon if rf-kill is on*/
        if (!iwl_is_ready_rf(priv))
@@ -916,131 +865,6 @@ static void iwl4965_set_rate(struct iwl_priv *priv)
                   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 }
 
-int iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
-{
-       unsigned long flags;
-
-       if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
-               return 0;
-
-       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
-                         disable_radio ? "OFF" : "ON");
-
-       if (disable_radio) {
-               iwl_scan_cancel(priv);
-               /* FIXME: This is a workaround for AP */
-               if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-                                   CSR_UCODE_SW_BIT_RFKILL);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       /* call the host command only if no hw rf-kill set */
-                       if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-                           iwl_is_ready(priv))
-                               iwl4965_send_card_state(priv,
-                                                       CARD_STATE_CMD_DISABLE,
-                                                       0);
-                       set_bit(STATUS_RF_KILL_SW, &priv->status);
-
-                       /* make sure mac80211 stop sending Tx frame */
-                       if (priv->mac80211_registered)
-                               ieee80211_stop_queues(priv->hw);
-               }
-               return 0;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-       clear_bit(STATUS_RF_KILL_SW, &priv->status);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* wake up ucode */
-       msleep(10);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_read32(priv, CSR_UCODE_DRV_GP1);
-       if (!iwl_grab_nic_access(priv))
-               iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-               IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-                                 "disabled by HW switch\n");
-               return 0;
-       }
-
-       if (priv->is_open)
-               queue_work(priv->workqueue, &priv->restart);
-       return 1;
-}
-
-#define IWL_PACKET_RETRY_TIME HZ
-
-int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-{
-       u16 sc = le16_to_cpu(header->seq_ctrl);
-       u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-       u16 frag = sc & IEEE80211_SCTL_FRAG;
-       u16 *last_seq, *last_frag;
-       unsigned long *last_time;
-
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_IBSS:{
-               struct list_head *p;
-               struct iwl4965_ibss_seq *entry = NULL;
-               u8 *mac = header->addr2;
-               int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
-
-               __list_for_each(p, &priv->ibss_mac_hash[index]) {
-                       entry = list_entry(p, struct iwl4965_ibss_seq, list);
-                       if (!compare_ether_addr(entry->mac, mac))
-                               break;
-               }
-               if (p == &priv->ibss_mac_hash[index]) {
-                       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
-                       if (!entry) {
-                               IWL_ERROR("Cannot malloc new mac entry\n");
-                               return 0;
-                       }
-                       memcpy(entry->mac, mac, ETH_ALEN);
-                       entry->seq_num = seq;
-                       entry->frag_num = frag;
-                       entry->packet_time = jiffies;
-                       list_add(&entry->list, &priv->ibss_mac_hash[index]);
-                       return 0;
-               }
-               last_seq = &entry->seq_num;
-               last_frag = &entry->frag_num;
-               last_time = &entry->packet_time;
-               break;
-       }
-       case IEEE80211_IF_TYPE_STA:
-               last_seq = &priv->last_seq_num;
-               last_frag = &priv->last_frag_num;
-               last_time = &priv->last_packet_time;
-               break;
-       default:
-               return 0;
-       }
-       if ((*last_seq == seq) &&
-           time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
-               if (*last_frag == frag)
-                       goto drop;
-               if (*last_frag + 1 != frag)
-                       /* out-of-order fragment */
-                       goto drop;
-       } else
-               *last_seq = seq;
-
-       *last_frag = frag;
-       *last_time = jiffies;
-       return 0;
-
- drop:
-       return 1;
-}
-
 #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
 
 #include "iwl-spectrum.h"
@@ -1419,17 +1243,6 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
                wake_up_interruptible(&priv->wait_command_queue);
 }
 
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-       priv->last_phy_res[0] = 1;
-       memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
-              sizeof(struct iwl4965_rx_phy_res));
-}
-
 /**
  * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
  *
@@ -1439,7 +1252,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
  * This function chains into the hardware specific files for them to setup
  * any hardware specific handlers as well.
  */
-static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+static void iwl_setup_rx_handlers(struct iwl_priv *priv)
 {
        priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
        priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
@@ -1456,8 +1269,8 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
         * statistics request from the host as well as for the periodic
         * statistics notifications (after received beacons) from the uCode.
         */
-       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
-       priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
+       priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
+       priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
 
        iwl_setup_rx_scan_handlers(priv);
 
@@ -1467,8 +1280,10 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
        priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
            iwl_rx_missed_beacon_notif;
        /* Rx handlers */
-       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
-       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
+       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
+       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
+       /* block ack */
+       priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
        /* Set up hardware specific Rx handlers */
        priv->cfg->ops->lib->rx_handler_setup(priv);
 }
@@ -1599,47 +1414,6 @@ void iwl_rx_handle(struct iwl_priv *priv)
        iwl_rx_queue_restock(priv);
 }
 
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95)   /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- *   about formulas used below. */
-int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
-       int sig_qual;
-       int degradation = PERFECT_RSSI - rssi_dbm;
-
-       /* If we get a noise measurement, use signal-to-noise ratio (SNR)
-        * as indicator; formula is (signal dbm - noise dbm).
-        * SNR at or above 40 is a great signal (100%).
-        * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
-        * Weakest usable signal is usually 10 - 15 dB SNR. */
-       if (noise_dbm) {
-               if (rssi_dbm - noise_dbm >= 40)
-                       return 100;
-               else if (rssi_dbm < noise_dbm)
-                       return 0;
-               sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
-       /* Else use just the signal level.
-        * This formula is a least squares fit of data points collected and
-        *   compared with a reference system that had a percentage (%) display
-        *   for signal quality. */
-       } else
-               sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
-                           (15 * RSSI_RANGE + 62 * degradation)) /
-                          (RSSI_RANGE * RSSI_RANGE);
-
-       if (sig_qual > 100)
-               sig_qual = 100;
-       else if (sig_qual < 1)
-               sig_qual = 0;
-
-       return sig_qual;
-}
-
 #ifdef CONFIG_IWLWIFI_DEBUG
 static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
 {
@@ -2002,7 +1776,7 @@ static void iwl4965_nic_start(struct iwl_priv *priv)
  */
 static int iwl4965_read_ucode(struct iwl_priv *priv)
 {
-       struct iwl4965_ucode *ucode;
+       struct iwl_ucode *ucode;
        int ret;
        const struct firmware *ucode_raw;
        const char *name = priv->cfg->fw_name;
@@ -2219,7 +1993,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
                goto restart;
        }
 
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
        ret = priv->cfg->ops->lib->alive_notify(priv);
        if (ret) {
                IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
@@ -2297,7 +2071,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
 
        iwl_leds_unregister(priv);
 
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        /* Unblock any waiting calls */
        wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2329,7 +2103,9 @@ static void __iwl4965_down(struct iwl_priv *priv)
                               test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
                               test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND;
+                                       STATUS_IN_SUSPEND |
+                              test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                                       STATUS_EXIT_PENDING;
                goto exit;
        }
 
@@ -2344,7 +2120,9 @@ static void __iwl4965_down(struct iwl_priv *priv)
                        test_bit(STATUS_IN_SUSPEND, &priv->status) <<
                                STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
-                               STATUS_FW_ERROR;
+                               STATUS_FW_ERROR |
+                      test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                               STATUS_EXIT_PENDING;
 
        spin_lock_irqsave(&priv->lock, flags);
        iwl_clear_bit(priv, CSR_GP_CNTRL,
@@ -2409,13 +2187,15 @@ static int __iwl4965_up(struct iwl_priv *priv)
        if (iwl_read32(priv, CSR_GP_CNTRL) &
                                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else {
+       else
                set_bit(STATUS_RF_KILL_HW, &priv->status);
-               if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-                       iwl_rfkill_set_hw_state(priv);
-                       IWL_WARNING("Radio disabled by HW RF Kill switch\n");
-                       return -ENODEV;
-               }
+
+       if (!test_bit(STATUS_IN_SUSPEND, &priv->status) &&
+           iwl_is_rfkill(priv)) {
+               iwl_rfkill_set_hw_state(priv);
+               IWL_WARNING("Radio disabled by %s RF Kill switch\n",
+                   test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+               return -ENODEV;
        }
 
        iwl_rfkill_set_hw_state(priv);
@@ -2459,7 +2239,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
 
        for (i = 0; i < MAX_HW_RESTARTS; i++) {
 
-               iwlcore_clear_stations_table(priv);
+               iwl_clear_stations_table(priv);
 
                /* load bootstrap state machine,
                 * load bootstrap program into processor's memory,
@@ -2712,7 +2492,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
 
        switch (priv->iw_mode) {
        case IEEE80211_IF_TYPE_STA:
-               iwl4965_rate_scale_init(priv->hw, IWL_AP_ID);
                break;
 
        case IEEE80211_IF_TYPE_IBSS:
@@ -2721,7 +2500,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
                priv->assoc_id = 1;
 
                iwl_rxon_add_station(priv, priv->bssid, 0);
-               iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
                iwl4965_send_beacon_cmd(priv);
 
                break;
@@ -2732,8 +2510,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
                break;
        }
 
-       iwl4965_sequence_reset(priv);
-
        /* Enable Rx differential gain and sensitivity calibrations */
        iwl_chain_noise_reset(priv);
        priv->start_calib = 1;
@@ -2982,13 +2758,14 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
 
        priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
 
-
-       if (priv->cfg->ops->lib->radio_kill_sw &&
-           priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled)) {
+       if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
                IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
-               mutex_unlock(&priv->mutex);
+               goto out;
        }
 
+       if (!conf->radio_enabled)
+               iwl_radio_kill_sw_disable_radio(priv);
+
        if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
                ret = -EIO;
@@ -3089,7 +2866,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
                return;
 
        /* The following should be done only at AP bring up */
-       if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
+       if (!(iwl_is_associated(priv))) {
 
                /* RXON - unassoc (to set timing command) */
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -3655,7 +3432,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter\n");
 
-       priv->lq_mngr.lq_ready = 0;
        spin_lock_irqsave(&priv->lock, flags);
        memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -3718,6 +3494,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
 {
        struct iwl_priv *priv = hw->priv;
        unsigned long flags;
+       __le64 timestamp;
 
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211("enter\n");
@@ -3742,6 +3519,8 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
        priv->ibss_beacon = skb;
 
        priv->assoc_id = 0;
+       timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+       priv->timestamp = le64_to_cpu(timestamp) +  (priv->beacon_int * 1000);
 
        IWL_DEBUG_MAC80211("leave\n");
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -3808,16 +3587,28 @@ static ssize_t show_version(struct device *d,
 {
        struct iwl_priv *priv = d->driver_data;
        struct iwl_alive_resp *palive = &priv->card_alive;
+       ssize_t pos = 0;
+       u16 eeprom_ver;
 
        if (palive->is_valid)
-               return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
-                                   "fw type: 0x%01X 0x%01X\n",
+               pos += sprintf(buf + pos,
+                               "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
+                               "fw type: 0x%01X 0x%01X\n",
                                palive->ucode_major, palive->ucode_minor,
                                palive->sw_rev[0], palive->sw_rev[1],
                                palive->ver_type, palive->ver_subtype);
-
        else
-               return sprintf(buf, "fw not loaded\n");
+               pos += sprintf(buf + pos, "fw not loaded\n");
+
+       if (priv->eeprom) {
+               eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+               pos += sprintf(buf + pos, "EEPROM version: 0x%x\n",
+                                eeprom_ver);
+       } else {
+               pos += sprintf(buf + pos, "EEPROM not initialzed\n");
+       }
+
+       return pos;
 }
 
 static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
@@ -4122,8 +3913,62 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
 static ssize_t show_channels(struct device *d,
                             struct device_attribute *attr, char *buf)
 {
-       /* all this shit doesn't belong into sysfs anyway */
-       return 0;
+
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       struct ieee80211_channel *channels = NULL;
+       const struct ieee80211_supported_band *supp_band = NULL;
+       int len = 0, i;
+       int count = 0;
+
+       if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+               return -EAGAIN;
+
+       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
+       channels = supp_band->channels;
+       count = supp_band->n_channels;
+
+       len += sprintf(&buf[len],
+                       "Displaying %d channels in 2.4GHz band "
+                       "(802.11bg):\n", count);
+
+       for (i = 0; i < count; i++)
+               len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+                               ieee80211_frequency_to_channel(
+                               channels[i].center_freq),
+                               channels[i].max_power,
+                               channels[i].flags & IEEE80211_CHAN_RADAR ?
+                               " (IEEE 802.11h required)" : "",
+                               (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                               || (channels[i].flags &
+                               IEEE80211_CHAN_RADAR)) ? "" :
+                               ", IBSS",
+                               channels[i].flags &
+                               IEEE80211_CHAN_PASSIVE_SCAN ?
+                               "passive only" : "active/passive");
+
+       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
+       channels = supp_band->channels;
+       count = supp_band->n_channels;
+
+       len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
+                       "(802.11a):\n", count);
+
+       for (i = 0; i < count; i++)
+               len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+                               ieee80211_frequency_to_channel(
+                               channels[i].center_freq),
+                               channels[i].max_power,
+                               channels[i].flags & IEEE80211_CHAN_RADAR ?
+                               " (IEEE 802.11h required)" : "",
+                               ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                               || (channels[i].flags &
+                               IEEE80211_CHAN_RADAR)) ? "" :
+                               ", IBSS",
+                               channels[i].flags &
+                               IEEE80211_CHAN_PASSIVE_SCAN ?
+                               "passive only" : "active/passive");
+
+       return len;
 }
 
 static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
@@ -4132,7 +3977,7 @@ static ssize_t show_statistics(struct device *d,
                               struct device_attribute *attr, char *buf)
 {
        struct iwl_priv *priv = dev_get_drvdata(d);
-       u32 size = sizeof(struct iwl4965_notif_statistics);
+       u32 size = sizeof(struct iwl_notif_statistics);
        u32 len = 0, ofs = 0;
        u8 *data = (u8 *) & priv->statistics;
        int rc = 0;
@@ -4438,7 +4283,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 
        iwl_setup_deferred_work(priv);
-       iwl4965_setup_rx_handlers(priv);
+       iwl_setup_rx_handlers(priv);
 
        /********************
         * 9. Conclude
@@ -4487,8 +4332,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
 {
        struct iwl_priv *priv = pci_get_drvdata(pdev);
-       struct list_head *p, *q;
-       int i;
        unsigned long flags;
 
        if (!priv)
@@ -4517,14 +4360,6 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       /* Free MAC hash list for ADHOC */
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
-               list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-                       list_del(p);
-                       kfree(list_entry(p, struct iwl4965_ibss_seq, list));
-               }
-       }
-
        iwl_rfkill_unregister(priv);
        iwl4965_dealloc_ucode_pci(priv);
 
@@ -4532,7 +4367,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
                iwl_rx_queue_free(priv, &priv->rxq);
        iwl_hw_txq_ctx_free(priv);
 
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
        iwl_eeprom_free(priv);