iwlwifi: trigger scan synchronously
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-3945.c
index ed59e27..51f1895 100644 (file)
@@ -184,19 +184,19 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
 {
        int idx;
 
-       for (idx = 0; idx < IWL_RATE_COUNT; idx++)
+       for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
                if (iwl3945_rates[idx].plcp == plcp)
                        return idx;
        return -1;
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
 
 static const char *iwl3945_get_tx_fail_reason(u32 status)
 {
        switch (status & TX_STATUS_MSK) {
-       case TX_STATUS_SUCCESS:
+       case TX_3945_STATUS_SUCCESS:
                return "SUCCESS";
                TX_STATUS_ENTRY(SHORT_LIMIT);
                TX_STATUS_ENTRY(LONG_LIMIT);
@@ -486,7 +486,7 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv,
                 *    but you can hack it to show more, if you'd like to. */
                if (dataframe)
                        IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, "
-                                    "len=%u, rssi=%d, chnl=%d, rate=%d, \n",
+                                    "len=%u, rssi=%d, chnl=%d, rate=%d,\n",
                                     title, le16_to_cpu(fc), header->addr1[5],
                                     length, rssi, channel, rate);
                else {
@@ -548,7 +548,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
        u16 len = le16_to_cpu(rx_hdr->len);
        struct sk_buff *skb;
-       int ret;
        __le16 fc = hdr->frame_control;
 
        /* We received data from the HW, so stop the watchdog */
@@ -565,9 +564,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
                return;
        }
 
-       skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
+       skb = dev_alloc_skb(128);
        if (!skb) {
-               IWL_ERR(priv, "alloc_skb failed\n");
+               IWL_ERR(priv, "dev_alloc_skb failed\n");
                return;
        }
 
@@ -576,37 +575,13 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
                                       (struct ieee80211_hdr *)rxb_addr(rxb),
                                       le32_to_cpu(rx_end->status), stats);
 
-       skb_reserve(skb, IWL_LINK_HDR_MAX);
        skb_add_rx_frag(skb, 0, rxb->page,
                        (void *)rx_hdr->payload - (void *)pkt, len);
 
-       /* mac80211 currently doesn't support paged SKB. Convert it to
-        * linear SKB for management frame and data frame requires
-        * software decryption or software defragementation. */
-       if (ieee80211_is_mgmt(fc) ||
-           ieee80211_has_protected(fc) ||
-           ieee80211_has_morefrags(fc) ||
-           le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
-               ret = skb_linearize(skb);
-       else
-               ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
-                       0 : -ENOMEM;
-
-       if (ret) {
-               kfree_skb(skb);
-               goto out;
-       }
-
-       /*
-        * XXX: We cannot touch the page and its virtual memory (pkt) after
-        * here. It might have already been freed by the above skb change.
-        */
-
        iwl_update_stats(priv, false, fc, len);
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
        ieee80211_rx(priv->hw, skb);
- out:
        priv->alloc_rxb_page--;
        rxb->page = NULL;
 }
@@ -622,9 +597,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
        struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-       int snr;
-       u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
-       u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
+       u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
+       u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
        u8 network_packet;
 
        rx_status.flag = 0;
@@ -662,43 +636,19 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
        /* Convert 3945's rssi indicator to dBm */
        rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
 
-       /* Set default noise value to -127 */
-       if (priv->last_rx_noise == 0)
-               priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-       /* 3945 provides noise info for OFDM frames only.
-        * sig_avg and noise_diff are measured by the 3945's digital signal
-        *   processor (DSP), and indicate linear levels of signal level and
-        *   distortion/noise within the packet preamble after
-        *   automatic gain control (AGC).  sig_avg should stay fairly
-        *   constant if the radio's AGC is working well.
-        * Since these values are linear (not dB or dBm), linear
-        *   signal-to-noise ratio (SNR) is (sig_avg / noise_diff).
-        * Convert linear SNR to dB SNR, then subtract that from rssi dBm
-        *   to obtain noise level in dBm.
-        * Calculate rx_status.signal (quality indicator in %) based on SNR. */
-       if (rx_stats_noise_diff) {
-               snr = rx_stats_sig_avg / rx_stats_noise_diff;
-               rx_status.noise = rx_status.signal -
-                                       iwl3945_calc_db_from_ratio(snr);
-       } else {
-               rx_status.noise = priv->last_rx_noise;
-       }
-
-
-       IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n",
-                       rx_status.signal, rx_status.noise,
-                       rx_stats_sig_avg, rx_stats_noise_diff);
+       IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
+                       rx_status.signal, rx_stats_sig_avg,
+                       rx_stats_noise_diff);
 
        header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
 
        network_packet = iwl3945_is_network_packet(priv, header);
 
-       IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
+       IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
                              network_packet ? '*' : ' ',
                              le16_to_cpu(rx_hdr->channel),
                              rx_status.signal, rx_status.signal,
-                             rx_status.noise, rx_status.rate_idx);
+                             rx_status.rate_idx);
 
        /* Set "1" to report good data frames in groups of 100 */
        iwl3945_dbg_report_frame(priv, pkt, header, 1);
@@ -709,7 +659,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
                        le32_to_cpu(rx_end->beacon_timestamp);
                priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
                priv->_3945.last_rx_rssi = rx_status.signal;
-               priv->last_rx_noise = rx_status.noise;
        }
 
        iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
@@ -806,7 +755,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
                                  int sta_id, int tx_id)
 {
        u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
-       u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
+       u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
        u16 rate_mask;
        int rate;
        u8 rts_retry_limit;
@@ -1049,7 +998,7 @@ static void iwl3945_nic_config(struct iwl_priv *priv)
        IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
 
        if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
-               IWL_DEBUG_INFO(priv, "RTP type \n");
+               IWL_DEBUG_INFO(priv, "RTP type\n");
        else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
                IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
                iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
@@ -1911,6 +1860,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
                                  "configuration (%d).\n", rc);
                        return rc;
                }
+               iwl_clear_ucode_stations(priv, false);
+               iwl_restore_stations(priv);
        }
 
        IWL_DEBUG_INFO(priv, "Sending RXON\n"
@@ -1941,7 +1892,10 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
 
        memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
 
-       iwl_clear_stations_table(priv);
+       if (!new_assoc) {
+               iwl_clear_ucode_stations(priv, false);
+               iwl_restore_stations(priv);
+       }
 
        /* 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 */
@@ -1951,19 +1905,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
                return rc;
        }
 
-       /* Add the broadcast address so we can send broadcast frames */
-       priv->cfg->ops->lib->add_bcast_station(priv);
-
-       /* 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 == NL80211_IFTYPE_STATION))
-               if (iwl_add_station(priv, priv->active_rxon.bssid_addr,
-                               true, CMD_SYNC, NULL) == IWL_INVALID_STATION) {
-                       IWL_ERR(priv, "Error adding AP address for transmit\n");
-                       return -EIO;
-               }
-
        /* Init the hardware's rate fallback order based on the band */
        rc = iwl3945_init_hw_rate_table(priv);
        if (rc) {
@@ -2147,7 +2088,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
 
                /* fill in channel group's nominal powers for each rate */
                for (rate_index = 0;
-                    rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) {
+                    rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
                        switch (rate_index) {
                        case IWL_RATE_36M_INDEX_TABLE:
                                if (i == 0)     /* B/G */
@@ -2799,6 +2740,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
        .get_hcmd_size = iwl3945_get_hcmd_size,
        .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
        .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
+       .request_scan = iwl3945_request_scan,
 };
 
 static const struct iwl_ops iwl3945_ops = {
@@ -2828,6 +2770,8 @@ static struct iwl_cfg iwl3945_bg_cfg = {
        .led_compensation = 64,
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .max_event_log_size = 512,
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2846,6 +2790,8 @@ static struct iwl_cfg iwl3945_abg_cfg = {
        .led_compensation = 64,
        .broken_powersave = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .max_event_log_size = 512,
 };
 
 DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {