return count;
 }
 
+static ssize_t iwl_dbgfs_internal_scan_write(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       char buf[8];
+       int buf_size;
+       int scan;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &scan) != 1)
+               return -EINVAL;
+
+       iwl_internal_short_hw_scan(priv);
+
+       return count;
+}
+
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
 DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
 DEBUGFS_READ_FILE_OPS(fh_reg);
 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
+DEBUGFS_WRITE_FILE_OPS(internal_scan);
 
 /*
  * Create the debugfs files and directories
        DEBUGFS_ADD_FILE(csr, debug, S_IWUSR);
        DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR);
        DEBUGFS_ADD_FILE(missed_beacon, debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(internal_scan, debug, S_IWUSR);
        if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
                DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR);
                DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_missed_beacon);
+       DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_internal_scan);
        if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
                        file_ucode_rx_stats);
 
 }
 EXPORT_SYMBOL(iwl_get_passive_dwell_time);
 
+static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
+                                    enum ieee80211_band band,
+                                    struct iwl_scan_channel *scan_ch)
+{
+       const struct ieee80211_supported_band *sband;
+       const struct iwl_channel_info *ch_info;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int i, added = 0;
+       u16 channel = 0;
+
+       sband = iwl_get_hw_mode(priv, band);
+       if (!sband) {
+               IWL_ERR(priv, "invalid band\n");
+               return added;
+       }
+
+       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+       /* only scan single channel, good enough to reset the RF */
+       /* pick the first valid not in-use channel */
+       if (band == IEEE80211_BAND_5GHZ) {
+               for (i = 14; i < priv->channel_count; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                               channel = priv->channel_info[i].channel;
+                               ch_info = iwl_get_channel_info(priv,
+                                       band, channel);
+                               if (is_channel_valid(ch_info))
+                                       break;
+                       }
+               }
+       } else {
+               for (i = 0; i < 14; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                                       channel =
+                                               priv->channel_info[i].channel;
+                                       ch_info = iwl_get_channel_info(priv,
+                                               band, channel);
+                                       if (is_channel_valid(ch_info))
+                                               break;
+                       }
+               }
+       }
+       if (channel) {
+               scan_ch->channel = cpu_to_le16(channel);
+               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* Set txpower levels to defaults */
+               scan_ch->dsp_atten = 110;
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+               added++;
+       } else
+               IWL_ERR(priv, "no valid channel found\n");
+       return added;
+}
+
 static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                                     enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
 
        IWL_DEBUG_INFO(priv, "Starting scan...\n");
        set_bit(STATUS_SCANNING, &priv->status);
+       priv->is_internal_short_scan = false;
        priv->scan_start = jiffies;
        priv->scan_pass_start = priv->scan_start;
 
 }
 EXPORT_SYMBOL(iwl_mac_hw_scan);
 
+/*
+ * internal short scan, this function should only been called while associated.
+ * It will reset and tune the radio to prevent possible RF related problem
+ */
+int iwl_internal_short_hw_scan(struct iwl_priv *priv)
+{
+       int ret = 0;
+
+       if (!iwl_is_ready_rf(priv)) {
+               ret = -EIO;
+               IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
+               goto out;
+       }
+       if (test_bit(STATUS_SCANNING, &priv->status)) {
+               IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+               ret = -EAGAIN;
+               goto out;
+       }
+       if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+               IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
+               ret = -EAGAIN;
+               goto out;
+       }
+       priv->scan_bands = 0;
+       if (priv->band == IEEE80211_BAND_5GHZ)
+               priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
+       else
+               priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+
+       IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
+       set_bit(STATUS_SCANNING, &priv->status);
+       priv->is_internal_short_scan = true;
+       queue_work(priv->workqueue, &priv->request_scan);
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL(iwl_internal_short_hw_scan);
+
 #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
 
 void iwl_bg_scan_check(struct work_struct *data)
        if (WARN_ON(left < ie_len))
                return len;
 
-       memcpy(pos, ies, ie_len);
+       if (ies)
+               memcpy(pos, ies, ie_len);
        len += ie_len;
        left -= ie_len;
 
                unsigned long flags;
 
                IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-
                spin_lock_irqsave(&priv->lock, flags);
                interval = priv->beacon_int;
                spin_unlock_irqrestore(&priv->lock, flags);
                               scan_suspend_time, interval);
        }
 
-       if (priv->scan_request->n_ssids) {
+       if (priv->is_internal_short_scan) {
+               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+       } else 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++) {
        rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
        rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
        scan->rx_chain = cpu_to_le16(rx_chain);
-       cmd_len = 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));
+       if (!priv->is_internal_short_scan) {
+               cmd_len = 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));
+       } else {
+               cmd_len = iwl_fill_probe_req(priv,
+                                       (struct ieee80211_mgmt *)scan->data,
+                                       NULL, 0,
+                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
 
+       }
        scan->tx_cmd.len = cpu_to_le16(cmd_len);
-
        if (iwl_is_monitor_mode(priv))
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
        scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
                               RXON_FILTER_BCON_AWARE_MSK);
 
-       scan->channel_count =
-               iwl_get_channels_for_scan(priv, band, is_active, n_probes,
-                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
-
+       if (priv->is_internal_short_scan) {
+               scan->channel_count =
+                       iwl_get_single_channel_for_scan(priv, band,
+                               (void *)&scan->data[le16_to_cpu(
+                               scan->tx_cmd.len)]);
+       } else {
+               scan->channel_count =
+                       iwl_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) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
                goto done;
 
        cancel_delayed_work(&priv->scan_check);
 
-       ieee80211_scan_completed(priv->hw, false);
+       if (!priv->is_internal_short_scan)
+               ieee80211_scan_completed(priv->hw, false);
+       else {
+               priv->is_internal_short_scan = false;
+               IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
+       }
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;