Пример #1
0
int iwl_scan_initiate(struct iwl_priv *priv)
{
	if (!iwl_is_ready_rf(priv)) {
		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
		return -EIO;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
		IWL_DEBUG_SCAN("Scan already in progress.\n");
		return -EAGAIN;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_SCAN("Scan request while abort pending\n");
		return -EAGAIN;
	}

	IWL_DEBUG_INFO("Starting scan...\n");
	if (priv->cfg->sku & IWL_SKU_G)
		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
	if (priv->cfg->sku & IWL_SKU_A)
		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
	set_bit(STATUS_SCANNING, &priv->status);
	priv->scan_start = jiffies;
	priv->scan_pass_start = priv->scan_start;

	queue_work(priv->workqueue, &priv->request_scan);

	return 0;
}
Пример #2
0
void iwl_bg_scan_completed(struct work_struct *work)
{
	struct iwl_priv *priv =
	    container_of(work, struct iwl_priv, scan_completed);
	bool internal = false;

	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");

	cancel_delayed_work(&priv->scan_check);

	mutex_lock(&priv->mutex);
	if (priv->is_internal_short_scan) {
		priv->is_internal_short_scan = false;
		IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
		internal = true;
	}
	mutex_unlock(&priv->mutex);

	/*
	 * Do not hold mutex here since this will cause mac80211 to call
	 * into driver again into functions that will attempt to take
	 * mutex.
	 */
	if (!internal)
		ieee80211_scan_completed(priv->hw, false);

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	/* Since setting the TXPOWER may have been deferred while
	 * performing the scan, fire one off */
	mutex_lock(&priv->mutex);
	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
	mutex_unlock(&priv->mutex);
}
Пример #3
0
Файл: scan.c Проект: 3bsa/linux
int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
{
	int ret;
	struct iwl_notification_wait wait_scan_done;
	static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
	bool sched = mvm->scan_status == IWL_MVM_SCAN_SCHED;

	lockdep_assert_held(&mvm->mutex);

	if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
		return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
					  notify);

	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
		return 0;

	if (iwl_mvm_is_radio_killed(mvm)) {
		ret = 0;
		goto out;
	}

	iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
				   scan_done_notif,
				   ARRAY_SIZE(scan_done_notif),
				   NULL, NULL);

	ret = iwl_mvm_send_scan_offload_abort(mvm);
	if (ret) {
		IWL_DEBUG_SCAN(mvm, "Send stop %sscan failed %d\n",
			       sched ? "offloaded " : "", ret);
		iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
		goto out;
	}

	IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
		       sched ? "offloaded " : "");

	ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
out:
	/*
	 * Clear the scan status so the next scan requests will succeed. This
	 * also ensures the Rx handler doesn't do anything, as the scan was
	 * stopped from above. Since the rx handler won't do anything now,
	 * we have to release the scan reference here.
	 */
	if (mvm->scan_status == IWL_MVM_SCAN_OS)
		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);

	mvm->scan_status = IWL_MVM_SCAN_NONE;

	if (notify) {
		if (sched)
			ieee80211_sched_scan_stopped(mvm->hw);
		else
			ieee80211_scan_completed(mvm->hw, true);
	}

	return ret;
}
Пример #4
0
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
		    struct ieee80211_vif *vif,
		    struct cfg80211_scan_request *req)
{
	struct iwl_priv *priv = hw->priv;
	int ret;

	IWL_DEBUG_MAC80211(priv, "enter\n");

	if (req->n_channels == 0)
		return -EINVAL;

	mutex_lock(&priv->mutex);

	if (!iwl_is_ready_rf(priv)) {
		ret = -EIO;
		IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
		goto out_unlock;
	}

	if (test_bit(STATUS_SCANNING, &priv->status) &&
	    !priv->is_internal_short_scan) {
		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
		ret = -EAGAIN;
		goto out_unlock;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
		ret = -EAGAIN;
		goto out_unlock;
	}

	/* mac80211 will only ask for one band at a time */
	priv->scan_band = req->channels[0]->band;
	priv->scan_request = req;
	priv->scan_vif = vif;

	/*
	 * If an internal scan is in progress, just set
	 * up the scan_request as per above.
	 */
	if (priv->is_internal_short_scan)
		ret = 0;
	else
		ret = iwl_scan_initiate(priv, vif);

	IWL_DEBUG_MAC80211(priv, "leave\n");

out_unlock:
	mutex_unlock(&priv->mutex);

	return ret;
}
Пример #5
0
static void iwl_process_scan_complete(struct iwl_priv *priv)
{
    bool aborted;

    lockdep_assert_held(&priv->mutex);

    if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->status))
        return;

    IWL_DEBUG_SCAN(priv, "Completed scan.\n");

    cancel_delayed_work(&priv->scan_check);

    aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
    if (aborted)
        IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");

    if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
        IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
        goto out_settings;
    }

    if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
        int err;

        /* Check if mac80211 requested scan during our internal scan */
        if (priv->scan_request == NULL)
            goto out_complete;

        /* If so request a new scan */
        err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
                                priv->scan_request->channels[0]->band);
        if (err) {
            IWL_DEBUG_SCAN(priv,
                           "failed to initiate pending scan: %d\n", err);
            aborted = true;
            goto out_complete;
        }

        return;
    }

out_complete:
    iwl_complete_scan(priv, aborted);

out_settings:
    /* Can we still talk to firmware ? */
    if (!iwl_is_ready_rf(priv))
        return;

    iwlagn_post_scan(priv);
}
Пример #6
0
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
                                      struct iwl_rx_cmd_buffer *rxb,
                                      struct iwl_device_cmd *cmd)
{
    struct iwl_rx_packet *pkt = rxb_addr(rxb);
    struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data;

    IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
                   scan_notif->scanned_channels,
                   scan_notif->tsf_low,
                   scan_notif->tsf_high, scan_notif->status);

    IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
                   (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
                   jiffies_to_msecs(jiffies - priv->scan_start));

    /*
     * When aborting, we run the scan completed background work inline
     * and the background work must then do nothing. The SCAN_COMPLETE
     * bit helps implement that logic and thus needs to be set before
     * queueing the work. Also, since the scan abort waits for SCAN_HW
     * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
     * to avoid a race there.
     */
    set_bit(STATUS_SCAN_COMPLETE, &priv->status);
    clear_bit(STATUS_SCAN_HW, &priv->status);
    queue_work(priv->workqueue, &priv->scan_completed);

    if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
            iwl_advanced_bt_coexist(priv) &&
            priv->bt_status != scan_notif->bt_status) {
        if (scan_notif->bt_status) {
            /* BT on */
            if (!priv->bt_ch_announce)
                priv->bt_traffic_load =
                    IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
            /*
             * otherwise, no traffic load information provided
             * no changes made
             */
        } else {
            /* BT off */
            priv->bt_traffic_load =
                IWL_BT_COEX_TRAFFIC_LOAD_NONE;
        }
        priv->bt_status = scan_notif->bt_status;
        queue_work(priv->workqueue,
                   &priv->bt_traffic_change_work);
    }
    return 0;
}
Пример #7
0
void iwl_bg_scan_completed(struct work_struct *work)
{
	struct iwl_priv *priv =
	    container_of(work, struct iwl_priv, scan_completed);
	bool internal = false;

	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");

	cancel_delayed_work(&priv->scan_check);

	mutex_lock(&priv->mutex);
	if (priv->is_internal_short_scan) {
		priv->is_internal_short_scan = false;
		IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
		internal = true;
	} else {
		priv->scan_request = NULL;
		priv->scan_vif = NULL;
	}

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		goto out;

	if (internal && priv->scan_request)
		iwl_scan_initiate(priv, priv->scan_vif);

	/* Since setting the TXPOWER may have been deferred while
	 * performing the scan, fire one off */
	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);

	/*
	 * Since setting the RXON may have been deferred while
	 * performing the scan, fire one off if needed
	 */
	if (memcmp(&priv->active_rxon,
		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
		iwlcore_commit_rxon(priv);

 out:
	mutex_unlock(&priv->mutex);

	/*
	 * Do not hold mutex here since this will cause mac80211 to call
	 * into driver again into functions that will attempt to take
	 * mutex.
	 */
	if (!internal)
		ieee80211_scan_completed(priv->hw, false);
}
Пример #8
0
void iwl_force_scan_end(struct iwl_priv *priv)
{
	lockdep_assert_held(&priv->mutex);

	if (!test_bit(STATUS_SCANNING, &priv->status)) {
		IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
		return;
	}

	IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
	clear_bit(STATUS_SCANNING, &priv->status);
	clear_bit(STATUS_SCAN_HW, &priv->status);
	clear_bit(STATUS_SCAN_ABORTING, &priv->status);
	iwl_complete_scan(priv, true);
}
Пример #9
0
/**
 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
 * @ms: amount of time to wait (in milliseconds) for scan to abort
 *
 */
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
    unsigned long timeout = jiffies + msecs_to_jiffies(ms);

    lockdep_assert_held(&priv->mutex);

    IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");

    iwl_do_scan_abort(priv);

    while (time_before_eq(jiffies, timeout)) {
        if (!test_bit(STATUS_SCAN_HW, &priv->status))
            goto finished;
        msleep(20);
    }

    return;

finished:
    /*
     * Now STATUS_SCAN_HW is clear. This means that the
     * device finished, but the background work is going
     * to execute at best as soon as we release the mutex.
     * Since we need to be able to issue a new scan right
     * after this function returns, run the complete here.
     * The STATUS_SCAN_COMPLETE bit will then be cleared
     * and prevent the background work from "completing"
     * a possible new scan.
     */
    iwl_process_scan_complete(priv);
}
/* Service SCAN_START_NOTIFICATION (0x82) */
static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
				    struct iwl_rx_mem_buffer *rxb,
				    struct iwl_device_cmd *cmd)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scanstart_notification *notif =
	    (struct iwl_scanstart_notification *)pkt->u.raw;
	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
	IWL_DEBUG_SCAN(priv, "Scan start: "
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       le32_to_cpu(notif->tsf_high),
		       le32_to_cpu(notif->tsf_low),
		       notif->status, notif->beacon_timer);

	if (priv->scan_type == IWL_SCAN_ROC &&
	    !priv->hw_roc_start_notified) {
		ieee80211_ready_on_channel(priv->hw);
		priv->hw_roc_start_notified = true;
	}

	return 0;
}
Пример #11
0
Файл: scan.c Проект: 3bsa/linux
static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
{
	int ret;
	struct iwl_host_cmd cmd = {
		.id = SCAN_OFFLOAD_ABORT_CMD,
	};
	u32 status;

	/* Exit instantly with error when device is not ready
	 * to receive scan abort command or it does not perform
	 * scheduled scan currently */
	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
		return -EIO;

	ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
	if (ret)
		return ret;

	if (status != CAN_ABORT_STATUS) {
		/*
		 * The scan abort will return 1 for success or
		 * 2 for "failure".  A failure condition can be
		 * due to simply not being in an active scan which
		 * can occur if we send the scan abort before the
		 * microcode has notified us that a scan is completed.
		 */
		IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status);
		ret = -ENOENT;
	}

	return ret;
}
Пример #12
0
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
				       struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;

	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
		       scan_notif->scanned_channels,
		       scan_notif->tsf_low,
		       scan_notif->tsf_high, scan_notif->status);
#endif

	/* The HW is no longer scanning */
	clear_bit(STATUS_SCAN_HW, &priv->status);

	IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
		       jiffies_to_msecs(elapsed_jiffies
					(priv->scan_start, jiffies)));

	/*
	 * If a request to abort was given, or the scan did not succeed
	 * then we reset the scan state machine and terminate,
	 * re-queuing another scan if one has been requested
	 */
	if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");

	IWL_DEBUG_INFO(priv, "Setting scan to off\n");

	clear_bit(STATUS_SCANNING, &priv->status);

	queue_work(priv->workqueue, &priv->scan_completed);
}
Пример #13
0
Файл: scan.c Проект: 3bsa/linux
int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
				    struct iwl_rx_cmd_buffer *rxb,
				    struct iwl_device_cmd *cmd)
{
	IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
	ieee80211_sched_scan_results(mvm->hw);

	return 0;
}
Пример #14
0
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl_rx_reply_scan(struct iwl_priv *priv,
                              struct iwl_rx_cmd_buffer *rxb)
{
#ifdef CPTCFG_IWLWIFI_DEBUG
    struct iwl_rx_packet *pkt = rxb_addr(rxb);
    struct iwl_scanreq_notification *notif = (void *)pkt->data;

    IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
#endif
}
Пример #15
0
int iwl_scan_cancel(struct iwl_priv *priv)
{
	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
		clear_bit(STATUS_SCANNING, &priv->status);
		return 0;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
		if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
			IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
			queue_work(priv->workqueue, &priv->abort_scan);

		} else
			IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n");

		return test_bit(STATUS_SCANNING, &priv->status);
	}

	return 0;
}
Пример #16
0
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
				       struct iwl_rx_mem_buffer *rxb)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;

	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
		       scan_notif->scanned_channels,
		       scan_notif->tsf_low,
		       scan_notif->tsf_high, scan_notif->status);

	/* The HW is no longer scanning */
	clear_bit(STATUS_SCAN_HW, &priv->status);

	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
		       jiffies_to_msecs(jiffies - priv->scan_start));

	queue_work(priv->workqueue, &priv->scan_completed);

	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
	    iwl_advanced_bt_coexist(priv) &&
	    priv->bt_status != scan_notif->bt_status) {
		if (scan_notif->bt_status) {
			/* BT on */
			if (!priv->bt_ch_announce)
				priv->bt_traffic_load =
					IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
			/*
			 * otherwise, no traffic load information provided
			 * no changes made
			 */
		} else {
			/* BT off */
			priv->bt_traffic_load =
				IWL_BT_COEX_TRAFFIC_LOAD_NONE;
		}
		priv->bt_status = scan_notif->bt_status;
		queue_work(priv->workqueue, &priv->bt_traffic_change_work);
	}
}
Пример #17
0
Файл: scan.c Проект: 3bsa/linux
int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm,
						struct iwl_rx_cmd_buffer *rxb,
						struct iwl_device_cmd *cmd)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_lmac_scan_complete_notif *notif = (void *)pkt->data;

	IWL_DEBUG_SCAN(mvm,
		       "Scan offload iteration complete: status=0x%x scanned channels=%d\n",
		       notif->status, notif->scanned_channels);
	return 0;
}
Пример #18
0
/* Service response to REPLY_SCAN_CMD (0x80) */
static int iwl_rx_reply_scan(struct iwl_priv *priv,
			      struct iwl_rx_cmd_buffer *rxb,
			      struct iwl_device_cmd *cmd)
{
#ifdef CONFIG_IWLWIFI_DEBUG
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scanreq_notification *notif = (void *)pkt->data;

	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
#endif
	return 0;
}
Пример #19
0
static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
{
    /* check if scan was requested from mac80211 */
    if (priv->scan_request) {
        IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
        ieee80211_scan_completed(priv->hw, aborted);
    }

    priv->scan_type = IWL_SCAN_NORMAL;
    priv->scan_vif = NULL;
    priv->scan_request = NULL;
}
Пример #20
0
void iwl_bg_start_internal_scan(struct work_struct *work)
{
	struct iwl_priv *priv =
		container_of(work, struct iwl_priv, start_internal_scan);

	mutex_lock(&priv->mutex);

	if (priv->is_internal_short_scan == true) {
		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
		goto unlock;
	}

	if (!iwl_is_ready_rf(priv)) {
		IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
		goto unlock;
	}

	if (test_bit(STATUS_SCANNING, &priv->status)) {
		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
		goto unlock;
	}

	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
		goto unlock;
	}

	priv->scan_band = priv->band;

	IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
	set_bit(STATUS_SCANNING, &priv->status);
	priv->is_internal_short_scan = true;

	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
		goto unlock;

	priv->cfg->ops->utils->request_scan(priv, NULL);
 unlock:
	mutex_unlock(&priv->mutex);
}
Пример #21
0
static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
				       struct iwl_rx_cmd_buffer *rxb,
				       struct iwl_device_cmd *cmd)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data;

	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
		       scan_notif->scanned_channels,
		       scan_notif->tsf_low,
		       scan_notif->tsf_high, scan_notif->status);

	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
		       jiffies_to_msecs(jiffies - priv->scan_start));

	set_bit(STATUS_SCAN_COMPLETE, &priv->status);
	clear_bit(STATUS_SCAN_HW, &priv->status);
	queue_work(priv->workqueue, &priv->scan_completed);

	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
	    iwl_advanced_bt_coexist(priv) &&
	    priv->bt_status != scan_notif->bt_status) {
		if (scan_notif->bt_status) {
			
			if (!priv->bt_ch_announce)
				priv->bt_traffic_load =
					IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
		} else {
			
			priv->bt_traffic_load =
				IWL_BT_COEX_TRAFFIC_LOAD_NONE;
		}
		priv->bt_status = scan_notif->bt_status;
		queue_work(priv->workqueue,
			   &priv->bt_traffic_change_work);
	}
	return 0;
}
Пример #22
0
static void iwl_do_scan_abort(struct iwl_priv *priv)
{
    int ret;

    lockdep_assert_held(&priv->mutex);

    if (!test_bit(STATUS_SCANNING, &priv->status)) {
        IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
        return;
    }

    if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
        IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
        return;
    }

    ret = iwl_send_scan_abort(priv);
    if (ret) {
        IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
        iwl_force_scan_end(priv);
    } else
        IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
}
Пример #23
0
static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
{
	int i, ind;

	ind = priv->scan_tx_ant[band];
	for (i = 0; i < priv->hw_params.tx_chains_num; i++) {
		ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1;
		if (priv->hw_params.valid_tx_ant & (1 << ind)) {
			priv->scan_tx_ant[band] = ind;
			break;
		}
	}
	IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
	return scan_tx_ant[ind];
}
Пример #24
0
/* Service SCAN_START_NOTIFICATION (0x82) */
static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
                                    struct iwl_rx_cmd_buffer *rxb)
{
    struct iwl_rx_packet *pkt = rxb_addr(rxb);
    struct iwl_scanstart_notification *notif = (void *)pkt->data;

    priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
    IWL_DEBUG_SCAN(priv, "Scan start: "
                   "%d [802.11%s] "
                   "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
                   notif->channel,
                   notif->band ? "bg" : "a",
                   le32_to_cpu(notif->tsf_high),
                   le32_to_cpu(notif->tsf_low),
                   notif->status, notif->beacon_timer);
}
Пример #25
0
/**
 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
 * @ms: amount of time to wait (in milliseconds) for scan to abort
 *
 */
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(ms);

	lockdep_assert_held(&priv->mutex);

	IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");

	iwl_do_scan_abort(priv);

	while (time_before_eq(jiffies, timeout)) {
		if (!test_bit(STATUS_SCAN_HW, &priv->status))
			break;
		msleep(20);
	}

	return test_bit(STATUS_SCAN_HW, &priv->status);
}
Пример #26
0
void iwl_bg_scan_check(struct work_struct *data)
{
	struct iwl_priv *priv =
	    container_of(data, struct iwl_priv, scan_check.work);

	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
		return;

	mutex_lock(&priv->mutex);
	if (test_bit(STATUS_SCANNING, &priv->status) &&
	    !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
		IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
			       jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));

		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
			iwl_send_scan_abort(priv);
	}
	mutex_unlock(&priv->mutex);
}
Пример #27
0
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
				      struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_scanresults_notification *notif =
	    (struct iwl_scanresults_notification *)pkt->u.raw;

	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
		       "%d [802.11%s] "
		       "(TSF: 0x%08X:%08X) - %d "
		       "elapsed=%lu usec\n",
		       notif->channel,
		       notif->band ? "bg" : "a",
		       le32_to_cpu(notif->tsf_high),
		       le32_to_cpu(notif->tsf_low),
		       le32_to_cpu(notif->statistics[0]),
		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
#endif
}
Пример #28
0
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
                                      struct iwl_rx_cmd_buffer *rxb)
{
#ifdef CPTCFG_IWLWIFI_DEBUG
    struct iwl_rx_packet *pkt = rxb_addr(rxb);
    struct iwl_scanresults_notification *notif = (void *)pkt->data;

    IWL_DEBUG_SCAN(priv, "Scan ch.res: "
                   "%d [802.11%s] "
                   "probe status: %u:%u "
                   "(TSF: 0x%08X:%08X) - %d "
                   "elapsed=%lu usec\n",
                   notif->channel,
                   notif->band ? "bg" : "a",
                   notif->probe_status, notif->num_probe_not_sent,
                   le32_to_cpu(notif->tsf_high),
                   le32_to_cpu(notif->tsf_low),
                   le32_to_cpu(notif->statistics[0]),
                   le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
#endif
}
Пример #29
0
Файл: scan.c Проект: 3bsa/linux
int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
					   struct iwl_rx_cmd_buffer *rxb,
					   struct iwl_device_cmd *cmd)
{
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_periodic_scan_complete *scan_notif;

	scan_notif = (void *)pkt->data;

	/* scan status must be locked for proper checking */
	lockdep_assert_held(&mvm->mutex);

	IWL_DEBUG_SCAN(mvm,
		       "%s completed, status %s, EBS status %s\n",
		       mvm->scan_status == IWL_MVM_SCAN_SCHED ?
				"Scheduled scan" : "Scan",
		       scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
				"completed" : "aborted",
		       scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
				"success" : "failed");


	/* only call mac80211 completion if the stop was initiated by FW */
	if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
		mvm->scan_status = IWL_MVM_SCAN_NONE;
		ieee80211_sched_scan_stopped(mvm->hw);
	} else if (mvm->scan_status == IWL_MVM_SCAN_OS) {
		mvm->scan_status = IWL_MVM_SCAN_NONE;
		ieee80211_scan_completed(mvm->hw,
				scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
		iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
	}

	if (scan_notif->ebs_status)
		mvm->last_ebs_successful = false;

	return 0;
}
Пример #30
0
static int iwl_send_scan_abort(struct iwl_priv *priv)
{
	int ret;
	struct iwl_rx_packet *pkt;
	struct iwl_host_cmd cmd = {
		.id = REPLY_SCAN_ABORT_CMD,
		.flags = CMD_WANT_SKB,
	};

	/* Exit instantly with error when device is not ready
	 * to receive scan abort command or it does not perform
	 * hardware scan currently */
	if (!test_bit(STATUS_READY, &priv->status) ||
	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
	    !test_bit(STATUS_SCAN_HW, &priv->status) ||
	    test_bit(STATUS_FW_ERROR, &priv->status) ||
	    test_bit(STATUS_EXIT_PENDING, &priv->status))
		return -EIO;

	ret = iwl_send_cmd_sync(priv, &cmd);
	if (ret)
		return ret;

	pkt = (struct iwl_rx_packet *)cmd.reply_page;
	if (pkt->u.status != CAN_ABORT_STATUS) {
		/* The scan abort will return 1 for success or
		 * 2 for "failure".  A failure condition can be
		 * due to simply not being in an active scan which
		 * can occur if we send the scan abort before we
		 * the microcode has notified us that a scan is
		 * completed. */
		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
		ret = -EIO;
	}

	iwl_free_pages(priv, cmd.reply_page);
	return ret;
}