Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / iwlwifi / iwl3945-base.c
index ad6f5eb..6b42ea2 100644 (file)
@@ -690,7 +690,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        dma_addr_t phys_addr;
        dma_addr_t txcmd_phys;
        int txq_id = skb_get_queue_mapping(skb);
-       u16 len, idx, len_org, hdr_len;
+       u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
        u8 id;
        u8 unicast;
        u8 sta_id;
@@ -729,7 +729,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* drop all data frame if we are not associated */
        if (ieee80211_is_data(fc) &&
-           (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
+           (!iwl_is_monitor_mode(priv)) && /* packet injection */
            (!iwl_is_associated(priv) ||
             ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
                IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
@@ -792,6 +792,40 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        /* Copy MAC header from skb into command buffer */
        memcpy(tx->hdr, hdr, hdr_len);
 
+
+       if (info->control.hw_key)
+               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
+
+       /* TODO need this for burst mode later on */
+       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
+
+       /* set is_hcca to 0; it probably will never be implemented */
+       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
+
+       /* Total # bytes to be transmitted */
+       len = (u16)skb->len;
+       tx->len = cpu_to_le16(len);
+
+
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+               if (qc)
+                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
+                    le16_to_cpu(out_cmd->hdr.sequence));
+       IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
+       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
+       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
+                          ieee80211_hdrlen(fc));
+
        /*
         * Use the first empty entry in this queue's command buffer array
         * to contain the Tx command and MAC header concatenated together
@@ -814,22 +848,18 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
-                                   out_cmd, sizeof(struct iwl_cmd),
-                                   PCI_DMA_TODEVICE);
+       txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+                                   len, PCI_DMA_TODEVICE);
+       /* we do not map meta data ... so we can safely access address to
+        * provide to unmap command*/
        pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
-       pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       txcmd_phys += offsetof(struct iwl_cmd, hdr);
+       pci_unmap_len_set(&out_cmd->meta, len, len);
 
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
        priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
                                                   txcmd_phys, len, 1, 0);
 
-       if (info->control.hw_key)
-               iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -842,32 +872,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                                                           0, U32_PAD(len));
        }
 
-       /* Total # bytes to be transmitted */
-       len = (u16)skb->len;
-       tx->len = cpu_to_le16(len);
-
-       /* TODO need this for burst mode later on */
-       iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-       /* set is_hcca to 0; it probably will never be implemented */
-       iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-       tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-               if (qc)
-                       priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
-
-       iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
-                          ieee80211_hdrlen(fc));
 
        /* Tell device the write index *just past* this latest filled TFD */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -1379,6 +1383,36 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
        spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
+void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+       unsigned long flags;
+       int i;
+       spin_lock_irqsave(&rxq->lock, flags);
+       INIT_LIST_HEAD(&rxq->rx_free);
+       INIT_LIST_HEAD(&rxq->rx_used);
+       /* Fill the rx_used queue with _all_ of the Rx buffers */
+       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+               /* In the reset function, these buffers may have been allocated
+                * to an SKB, so we need to unmap and free potential storage */
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       priv->alloc_rxb_skb--;
+                       dev_kfree_skb(rxq->pool[i].skb);
+                       rxq->pool[i].skb = NULL;
+               }
+               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+       }
+
+       /* Set us so that we have processed and used all buffers, but have
+        * not restocked the Rx queue with fresh buffers */
+       rxq->read = rxq->write = 0;
+       rxq->free_count = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
 /*
  * this should be called while priv->lock is locked
  */
@@ -1403,6 +1437,33 @@ void iwl3945_rx_replenish(void *data)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+       int i;
+       for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+               if (rxq->pool[i].skb != NULL) {
+                       pci_unmap_single(priv->pci_dev,
+                                        rxq->pool[i].real_dma_addr,
+                                        priv->hw_params.rx_buf_size,
+                                        PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb(rxq->pool[i].skb);
+               }
+       }
+
+       pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+                           rxq->dma_addr);
+       pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+                           rxq->rb_stts, rxq->rb_stts_dma);
+       rxq->bd = NULL;
+       rxq->rb_stts  = NULL;
+}
+
+
 /* Convert linear signal-to-noise ratio into dB */
 static u8 ratio2dB[100] = {
 /*      0   1   2   3   4   5   6   7   8   9 */
@@ -1520,9 +1581,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
-                                           priv->hw_params.rx_buf_size,
-                                           PCI_DMA_FROMDEVICE);
+               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
+                               priv->hw_params.rx_buf_size,
+                               PCI_DMA_FROMDEVICE);
                pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
                /* Reclaim a command buffer only if this packet is a response
@@ -1543,6 +1604,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                                "r = %d, i = %d, %s, 0x%02x\n", r, i,
                                get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
                        priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+                       priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
                } else {
                        /* No handling needed */
                        IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
@@ -1570,9 +1632,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
                        rxb->skb = NULL;
                }
 
-               pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
-                               priv->hw_params.rx_buf_size,
-                               PCI_DMA_FROMDEVICE);
                spin_lock_irqsave(&rxq->lock, flags);
                list_add_tail(&rxb->list, &priv->rxq.rx_used);
                spin_unlock_irqrestore(&rxq->lock, flags);
@@ -1845,6 +1904,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                /* Tell the device to stop sending interrupts */
                iwl_disable_interrupts(priv);
 
+               priv->isr_stats.hw++;
                iwl_irq_handle_error(priv);
 
                handled |= CSR_INT_BIT_HW_ERR;
@@ -1857,13 +1917,17 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #ifdef CONFIG_IWLWIFI_DEBUG
        if (priv->debug_level & (IWL_DL_ISR)) {
                /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD)
+               if (inta & CSR_INT_BIT_SCD) {
                        IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
                                      "the frame/frames.\n");
+                       priv->isr_stats.sch++;
+               }
 
                /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE)
+               if (inta & CSR_INT_BIT_ALIVE) {
                        IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+                       priv->isr_stats.alive++;
+               }
        }
 #endif
        /* Safely ignore these bits for debug checks below */
@@ -1873,6 +1937,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
        if (inta & CSR_INT_BIT_SW_ERR) {
                IWL_ERR(priv, "Microcode SW error detected. "
                        "Restarting 0x%X.\n", inta);
+               priv->isr_stats.sw++;
+               priv->isr_stats.sw_err = inta;
                iwl_irq_handle_error(priv);
                handled |= CSR_INT_BIT_SW_ERR;
        }
@@ -1888,6 +1954,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                iwl_txq_update_write_ptr(priv, &priv->txq[4]);
                iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
+               priv->isr_stats.wakeup++;
                handled |= CSR_INT_BIT_WAKEUP;
        }
 
@@ -1896,11 +1963,13 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
         * notifications from uCode come through here*/
        if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
                iwl3945_rx_handle(priv);
+               priv->isr_stats.rx++;
                handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
        }
 
        if (inta & CSR_INT_BIT_FH_TX) {
                IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+               priv->isr_stats.tx++;
 
                iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
                if (!iwl_grab_nic_access(priv)) {
@@ -1911,8 +1980,10 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
                handled |= CSR_INT_BIT_FH_TX;
        }
 
-       if (inta & ~handled)
+       if (inta & ~handled) {
                IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               priv->isr_stats.unhandled++;
+       }
 
        if (inta & ~CSR_INI_SET_MASK) {
                IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
@@ -2942,9 +3013,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        int rc = 0;
        struct iwl3945_scan_cmd *scan;
        struct ieee80211_conf *conf = NULL;
-       u8 n_probes = 2;
+       u8 n_probes = 0;
        enum ieee80211_band band;
-       DECLARE_SSID_BUF(ssid);
+       bool is_active = false;
 
        conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -3043,18 +3114,25 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                               scan_suspend_time, interval);
        }
 
-       /* We should add the ability for user to lock to PASSIVE ONLY */
-       if (priv->one_direct_scan) {
-               IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n",
-                               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++;
+       if (priv->scan_request->n_ssids) {
+               int i, p = 0;
+               IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+               for (i = 0; i < priv->scan_request->n_ssids; i++) {
+                       /* always does wildcard anyway */
+                       if (!priv->scan_request->ssids[i].ssid_len)
+                               continue;
+                       scan->direct_scan[p].id = WLAN_EID_SSID;
+                       scan->direct_scan[p].len =
+                               priv->scan_request->ssids[i].ssid_len;
+                       memcpy(scan->direct_scan[p].ssid,
+                              priv->scan_request->ssids[i].ssid,
+                              priv->scan_request->ssids[i].ssid_len);
+                       n_probes++;
+                       p++;
+               }
+               is_active = true;
        } else
-               IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n");
+               IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
 
        /* We don't build a direct scan probe request; the uCode will do
         * that based on the direct_mask added to each channel entry */
@@ -3071,7 +3149,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                band = IEEE80211_BAND_2GHZ;
        } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-               scan->good_CRC_th = IWL_GOOD_CRC_TH;
+               /*
+                * If active scaning is requested but a certain channel
+                * is marked passive, we can do active scanning if we
+                * detect transmissions.
+                */
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
                band = IEEE80211_BAND_5GHZ;
        } else {
                IWL_WARN(priv, "Invalid scan band count\n");
@@ -3079,19 +3162,20 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        }
 
        scan->tx_cmd.len = cpu_to_le16(
-               iwl_fill_probe_req(priv, band,
-                                  (struct ieee80211_mgmt *)scan->data,
-                                  IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+                       iwl_fill_probe_req(priv,
+                               (struct ieee80211_mgmt *)scan->data,
+                               priv->scan_request->ie,
+                               priv->scan_request->ie_len,
+                               IWL_MAX_SCAN_SIZE - sizeof(*scan)));
 
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
+       if (iwl_is_monitor_mode(priv))
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
        scan->channel_count =
-               iwl3945_get_channels_for_scan(priv, band, 1, /* active */
-                                             n_probes,
+               iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
                        (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
        if (scan->channel_count == 0) {
@@ -3436,106 +3520,6 @@ void iwl3945_config_ap(struct iwl_priv *priv)
         * clear sta table, add BCAST sta... */
 }
 
-static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
-                                       struct ieee80211_vif *vif,
-                                       struct ieee80211_if_conf *conf)
-{
-       struct iwl_priv *priv = hw->priv;
-       int rc;
-
-       if (conf == NULL)
-               return -EIO;
-
-       if (priv->vif != vif) {
-               IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
-               return 0;
-       }
-
-       /* handle this temporarily here */
-       if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-           conf->changed & IEEE80211_IFCC_BEACON) {
-               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-               if (!beacon)
-                       return -ENOMEM;
-               mutex_lock(&priv->mutex);
-               rc = iwl_mac_beacon_update(hw, beacon);
-               mutex_unlock(&priv->mutex);
-               if (rc)
-                       return rc;
-       }
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       mutex_lock(&priv->mutex);
-
-       if (conf->bssid)
-               IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", 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 (priv->iw_mode == NL80211_IFTYPE_AP) {
-               if (!conf->bssid) {
-                       conf->bssid = priv->mac_addr;
-                       memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-                       IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
-                                          conf->bssid);
-               }
-               if (priv->ibss_beacon)
-                       dev_kfree_skb(priv->ibss_beacon);
-
-               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
-       }
-
-       if (iwl_is_rfkill(priv))
-               goto done;
-
-       if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-           !is_multicast_ether_addr(conf->bssid)) {
-               /* If there is currently a HW scan going on in the background
-                * then we need to cancel it else the RXON below will fail. */
-               if (iwl_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARN(priv, "Aborted scan still in progress "
-                                   "after 100ms\n");
-                       IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n");
-                       mutex_unlock(&priv->mutex);
-                       return -EAGAIN;
-               }
-               memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
-
-               /* TODO: Audit driver for usage of these members and see
-                * if mac80211 deprecates them (priv->bssid looks like it
-                * shouldn't be there, but I haven't scanned the IBSS code
-                * to verify) - jpk */
-               memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-
-               if (priv->iw_mode == NL80211_IFTYPE_AP)
-                       iwlcore_config_ap(priv);
-               else {
-                       rc = iwlcore_commit_rxon(priv);
-                       if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
-                               priv->cfg->ops->smgmt->add_station(priv,
-                                       priv->active_rxon.bssid_addr, 1, 0, NULL);
-               }
-
-       } else {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwlcore_commit_rxon(priv);
-       }
-
- done:
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-       mutex_unlock(&priv->mutex);
-
-       return 0;
-}
-
 static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                               struct ieee80211_vif *vif,
                               struct ieee80211_sta *sta,
@@ -3594,99 +3578,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
-static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
-                               struct ieee80211_tx_queue_stats *stats)
-{
-       struct iwl_priv *priv = hw->priv;
-       int i, avail;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       unsigned long flags;
-
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       for (i = 0; i < AC_NUM; i++) {
-               txq = &priv->txq[i];
-               q = &txq->q;
-               avail = iwl_queue_space(q);
-
-               stats[i].len = q->n_window - avail;
-               stats[i].limit = q->n_window - q->high_mark;
-               stats[i].count = q->n_window;
-
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-       return 0;
-}
-
-static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-       struct iwl_priv *priv = hw->priv;
-       unsigned long flags;
-
-       mutex_lock(&priv->mutex);
-       IWL_DEBUG_MAC80211(priv, "enter\n");
-
-       iwl_reset_qos(priv);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = 0;
-       priv->assoc_capability = 0;
-
-       /* new association get rid of ibss beacon skb */
-       if (priv->ibss_beacon)
-               dev_kfree_skb(priv->ibss_beacon);
-
-       priv->ibss_beacon = NULL;
-
-       priv->beacon_int = priv->hw->conf.beacon_int;
-       priv->timestamp = 0;
-       if ((priv->iw_mode == NL80211_IFTYPE_STATION))
-               priv->beacon_int = 0;
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!iwl_is_ready_rf(priv)) {
-               IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       /* we are restarting association process
-        * clear RXON_FILTER_ASSOC_MSK bit
-       */
-       if (priv->iw_mode != NL80211_IFTYPE_AP) {
-               iwl_scan_cancel_timeout(priv, 100);
-               priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-               iwlcore_commit_rxon(priv);
-       }
-
-       /* Per mac80211.h: This is only used in IBSS mode... */
-       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
-               IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
-               mutex_unlock(&priv->mutex);
-               return;
-       }
-
-       iwl_set_rate(priv);
-
-       mutex_unlock(&priv->mutex);
-
-       IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -4213,12 +4104,12 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .add_interface = iwl_mac_add_interface,
        .remove_interface = iwl_mac_remove_interface,
        .config = iwl_mac_config,
-       .config_interface = iwl3945_mac_config_interface,
+       .config_interface = iwl_mac_config_interface,
        .configure_filter = iwl_configure_filter,
        .set_key = iwl3945_mac_set_key,
-       .get_tx_stats = iwl3945_mac_get_tx_stats,
+       .get_tx_stats = iwl_mac_get_tx_stats,
        .conf_tx = iwl_mac_conf_tx,
-       .reset_tsf = iwl3945_mac_reset_tsf,
+       .reset_tsf = iwl_mac_reset_tsf,
        .bss_info_changed = iwl_bss_info_changed,
        .hw_scan = iwl_mac_hw_scan
 };
@@ -4312,7 +4203,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        hw->wiphy->custom_regulatory = true;
 
-       hw->wiphy->max_scan_ssids = 1; /* WILL FIX */
+       hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+       /* we create the 802.11 header and a zero-length SSID element */
+       hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
 
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
@@ -4474,20 +4367,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_INFO(priv, "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_mod_params.disable) {
-               set_bit(STATUS_RF_KILL_SW, &priv->status);
-               IWL_DEBUG_INFO(priv, "Radio disabled.\n");
-       }
-
-
        /***********************
-        * 8. Setup Services
+        * 7. Setup Services
         * ********************/
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -4515,7 +4396,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        iwl3945_setup_rx_handlers(priv);
 
        /*********************************
-        * 9. Setup and Register mac80211
+        * 8. Setup and Register mac80211
         * *******************************/
 
        iwl_enable_interrupts(priv);
@@ -4524,6 +4405,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if (err)
                goto  out_remove_sysfs;
 
+       err = iwl_dbgfs_register(priv, DRV_NAME);
+       if (err)
+               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
        err = iwl_rfkill_init(priv);
        if (err)
                IWL_ERR(priv, "Unable to initialize RFKILL system. "
@@ -4574,6 +4459,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
+       iwl_dbgfs_unregister(priv);
+
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 
        if (priv->mac80211_registered) {
@@ -4595,12 +4482,12 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
        iwl_rfkill_unregister(priv);
-       cancel_delayed_work(&priv->rfkill_poll);
+       cancel_delayed_work_sync(&priv->rfkill_poll);
 
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
-               iwl_rx_queue_free(priv, &priv->rxq);
+               iwl3945_rx_queue_free(priv, &priv->rxq);
        iwl3945_hw_txq_ctx_free(priv);
 
        iwl3945_unset_hw_params(priv);
@@ -4687,8 +4574,6 @@ MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
 
 module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto,
                 "using software crypto (default 1 [software])\n");