예제 #1
0
static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{
    struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);

    flush_work(&mvm->async_handlers_wk);

    mutex_lock(&mvm->mutex);
    /* async_handlers_wk is now blocked */

    /*
     * The work item could be running or queued if the
     * ROC time event stops just as we get here.
     */
    cancel_work_sync(&mvm->roc_done_wk);

    iwl_trans_stop_device(mvm->trans);
    iwl_trans_stop_hw(mvm->trans, false);

    iwl_mvm_async_handlers_purge(mvm);
    /* async_handlers_list is empty and will stay empty: HW is stopped */

    /* the fw is stopped, the aux sta is dead: clean up driver state */
    iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);

    mutex_unlock(&mvm->mutex);

    /*
     * The worker might have been waiting for the mutex, let it run and
     * discover that its list is now empty.
     */
    cancel_work_sync(&mvm->async_handlers_wk);
}
예제 #2
0
static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
					 struct ieee80211_vif *vif)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

	iwl_mvm_prepare_mac_removal(mvm, vif);

	mutex_lock(&mvm->mutex);

	iwl_mvm_vif_dbgfs_clean(mvm, vif);

	/*
	 * For AP/GO interface, the tear down of the resources allocated to the
	 * interface is be handled as part of the stop_ap flow.
	 */
	if (vif->type == NL80211_IFTYPE_AP) {
		iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
		goto out_release;
	}

	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
		mvm->p2p_device_vif = NULL;
		iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
		iwl_mvm_binding_remove_vif(mvm, vif);
		iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
		mvmvif->phy_ctxt = NULL;
	}

	/*
	 * TODO: remove this temporary code.
	 * Currently MVM FW supports power management only on single MAC.
	 * Check if only one additional interface remains after removing
	 * current one. Update power mode on the remaining interface.
	 */
	if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
		mvm->vif_count--;
	IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
			   mvm->vif_count);
	if (mvm->vif_count == 1) {
		ieee80211_iterate_active_interfaces(
					mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
					iwl_mvm_power_update_iterator, mvm);
	}

	iwl_mvm_mac_ctxt_remove(mvm, vif);

out_release:
	iwl_mvm_mac_ctxt_release(mvm, vif);
	mutex_unlock(&mvm->mutex);
}
예제 #3
0
static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
        struct ieee80211_vif *vif)
{
    struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
    struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    u32 tfd_msk = 0, ac;

    for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
        if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
            tfd_msk |= BIT(vif->hw_queue[ac]);

    if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
        tfd_msk |= BIT(vif->cab_queue);

    if (tfd_msk) {
        mutex_lock(&mvm->mutex);
        iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
        mutex_unlock(&mvm->mutex);
    }

    if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
        /*
         * Flush the ROC worker which will flush the OFFCHANNEL queue.
         * We assume here that all the packets sent to the OFFCHANNEL
         * queue are sent in ROC session.
         */
        flush_work(&mvm->roc_done_wk);
    } else {
        /*
         * By now, all the AC queues are empty. The AGG queues are
         * empty too. We already got all the Tx responses for all the
         * packets in the queues. The drain work can have been
         * triggered. Flush it. This work item takes the mutex, so kill
         * it before we take it.
         */
        flush_work(&mvm->sta_drained_wk);
    }

    mutex_lock(&mvm->mutex);

    /*
     * For AP/GO interface, the tear down of the resources allocated to the
     * interface should be handled as part of the bss_info_changed flow.
     */
    if (vif->type == NL80211_IFTYPE_AP) {
        iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
        goto out_release;
    }

    if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
        mvm->p2p_device_vif = NULL;
        iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
        iwl_mvm_binding_remove_vif(mvm, vif);
        iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt);
        mvmvif->phy_ctxt = NULL;
    }

    /*
     * TODO: remove this temporary code.
     * Currently MVM FW supports power management only on single MAC.
     * Check if only one additional interface remains after removing
     * current one. Update power mode on the remaining interface.
     */
    if (mvm->vif_count)
        mvm->vif_count--;
    IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
                       mvm->vif_count);
    if (mvm->vif_count == 1) {
        ieee80211_iterate_active_interfaces(
            mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
            iwl_mvm_power_update_iterator, mvm);
    }

    iwl_mvm_mac_ctxt_remove(mvm, vif);

out_release:
    iwl_mvm_mac_ctxt_release(mvm, vif);
    mutex_unlock(&mvm->mutex);
}