aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatti Gottlieb <matti.gottlieb@intel.com>2014-11-16 03:25:12 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-24 01:30:14 -0500
commitbf5da87f60a920599c46382d95b8e9c4ef8da37e (patch)
treeaa62a6c7a7f210fa86a9db9cba9fd6896551f029
parent2992a324e35e49f3ea950938c91b6b2108bbbf4c (diff)
iwlwifi: mvm: add remove flow for AUX ROC time events
Add a flow that handles the requests to cancel the roc time event, that has been triggered via the aux framework. The roc for bss is different than the roc for p2p devices, and is done via the aux framework using the aux queue, thus requires a different flow to cancel the time event. Signed-off-by: Matti Gottlieb <matti.gottlieb@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c107
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.h4
3 files changed, 89 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index d37d5a8b383e..f3379d76f3db 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2652,7 +2652,7 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
2652 IWL_DEBUG_MAC80211(mvm, "enter\n"); 2652 IWL_DEBUG_MAC80211(mvm, "enter\n");
2653 2653
2654 mutex_lock(&mvm->mutex); 2654 mutex_lock(&mvm->mutex);
2655 iwl_mvm_stop_p2p_roc(mvm); 2655 iwl_mvm_stop_roc(mvm);
2656 mutex_unlock(&mvm->mutex); 2656 mutex_unlock(&mvm->mutex);
2657 2657
2658 IWL_DEBUG_MAC80211(mvm, "leave\n"); 2658 IWL_DEBUG_MAC80211(mvm, "leave\n");
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 6dfad230be5e..8cf246b695c4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -549,18 +549,11 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
549 } 549 }
550} 550}
551 551
552/* 552static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
553 * Explicit request to remove a time event. The removal of a time event needs to 553 struct iwl_mvm_time_event_data *te_data,
554 * be synchronized with the flow of a time event's end notification, which also 554 u32 *uid)
555 * removes the time event from the op mode data structures.
556 */
557void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
558 struct iwl_mvm_vif *mvmvif,
559 struct iwl_mvm_time_event_data *te_data)
560{ 555{
561 struct iwl_time_event_cmd time_cmd = {}; 556 u32 id;
562 u32 id, uid;
563 int ret;
564 557
565 /* 558 /*
566 * It is possible that by the time we got to this point the time 559 * It is possible that by the time we got to this point the time
@@ -569,7 +562,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
569 spin_lock_bh(&mvm->time_event_lock); 562 spin_lock_bh(&mvm->time_event_lock);
570 563
571 /* Save time event uid before clearing its data */ 564 /* Save time event uid before clearing its data */
572 uid = te_data->uid; 565 *uid = te_data->uid;
573 id = te_data->id; 566 id = te_data->id;
574 567
575 /* 568 /*
@@ -584,10 +577,59 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
584 * send a removal command. 577 * send a removal command.
585 */ 578 */
586 if (id == TE_MAX) { 579 if (id == TE_MAX) {
587 IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", uid); 580 IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
588 return; 581 return false;
589 } 582 }
590 583
584 return true;
585}
586
587/*
588 * Explicit request to remove a aux roc time event. The removal of a time
589 * event needs to be synchronized with the flow of a time event's end
590 * notification, which also removes the time event from the op mode
591 * data structures.
592 */
593static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm,
594 struct iwl_mvm_vif *mvmvif,
595 struct iwl_mvm_time_event_data *te_data)
596{
597 struct iwl_hs20_roc_req aux_cmd = {};
598 u32 uid;
599 int ret;
600
601 if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
602 return;
603
604 aux_cmd.event_unique_id = cpu_to_le32(uid);
605 aux_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
606 aux_cmd.id_and_color =
607 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
608 IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n",
609 le32_to_cpu(aux_cmd.event_unique_id));
610 ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0,
611 sizeof(aux_cmd), &aux_cmd);
612
613 if (WARN_ON(ret))
614 return;
615}
616
617/*
618 * Explicit request to remove a time event. The removal of a time event needs to
619 * be synchronized with the flow of a time event's end notification, which also
620 * removes the time event from the op mode data structures.
621 */
622void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
623 struct iwl_mvm_vif *mvmvif,
624 struct iwl_mvm_time_event_data *te_data)
625{
626 struct iwl_time_event_cmd time_cmd = {};
627 u32 uid;
628 int ret;
629
630 if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
631 return;
632
591 /* When we remove a TE, the UID is to be set in the id field */ 633 /* When we remove a TE, the UID is to be set in the id field */
592 time_cmd.id = cpu_to_le32(uid); 634 time_cmd.id = cpu_to_le32(uid);
593 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE); 635 time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
@@ -666,13 +708,17 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
666 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 708 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
667} 709}
668 710
669void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm) 711void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
670{ 712{
671 struct iwl_mvm_vif *mvmvif; 713 struct iwl_mvm_vif *mvmvif;
672 struct iwl_mvm_time_event_data *te_data; 714 struct iwl_mvm_time_event_data *te_data;
715 bool is_p2p = false;
673 716
674 lockdep_assert_held(&mvm->mutex); 717 lockdep_assert_held(&mvm->mutex);
675 718
719 mvmvif = NULL;
720 spin_lock_bh(&mvm->time_event_lock);
721
676 /* 722 /*
677 * Iterate over the list of time events and find the time event that is 723 * Iterate over the list of time events and find the time event that is
678 * associated with a P2P_DEVICE interface. 724 * associated with a P2P_DEVICE interface.
@@ -680,22 +726,41 @@ void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
680 * event at any given time and this time event coresponds to a ROC 726 * event at any given time and this time event coresponds to a ROC
681 * request 727 * request
682 */ 728 */
683 mvmvif = NULL;
684 spin_lock_bh(&mvm->time_event_lock);
685 list_for_each_entry(te_data, &mvm->time_event_list, list) { 729 list_for_each_entry(te_data, &mvm->time_event_list, list) {
686 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { 730 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE &&
731 te_data->running) {
687 mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); 732 mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
688 break; 733 is_p2p = true;
734 goto remove_te;
735 }
736 }
737
738 /*
739 * Iterate over the list of aux roc time events and find the time
740 * event that is associated with a BSS interface.
741 * This assumes that a BSS interface can have only a single time
742 * event at any given time and this time event coresponds to a ROC
743 * request
744 */
745 list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
746 if (te_data->running) {
747 mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
748 goto remove_te;
689 } 749 }
690 } 750 }
751
752remove_te:
691 spin_unlock_bh(&mvm->time_event_lock); 753 spin_unlock_bh(&mvm->time_event_lock);
692 754
693 if (!mvmvif) { 755 if (!mvmvif) {
694 IWL_WARN(mvm, "P2P_DEVICE no remain on channel event\n"); 756 IWL_WARN(mvm, "No remain on channel event\n");
695 return; 757 return;
696 } 758 }
697 759
698 iwl_mvm_remove_time_event(mvm, mvmvif, te_data); 760 if (is_p2p)
761 iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
762 else
763 iwl_mvm_remove_aux_roc_te(mvm, mvmvif, te_data);
699 764
700 iwl_mvm_roc_finished(mvm); 765 iwl_mvm_roc_finished(mvm);
701} 766}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index b350e47e19da..6f6b35db3ab8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -182,14 +182,14 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
182 int duration, enum ieee80211_roc_type type); 182 int duration, enum ieee80211_roc_type type);
183 183
184/** 184/**
185 * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity 185 * iwl_mvm_stop_roc - stop remain on channel functionality
186 * @mvm: the mvm component 186 * @mvm: the mvm component
187 * 187 *
188 * This function can be used to cancel an ongoing ROC session. 188 * This function can be used to cancel an ongoing ROC session.
189 * The function is async, it will instruct the FW to stop serving the ROC 189 * The function is async, it will instruct the FW to stop serving the ROC
190 * session, but will not wait for the actual stopping of the session. 190 * session, but will not wait for the actual stopping of the session.
191 */ 191 */
192void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm); 192void iwl_mvm_stop_roc(struct iwl_mvm *mvm);
193 193
194/** 194/**
195 * iwl_mvm_remove_time_event - general function to clean up of time event 195 * iwl_mvm_remove_time_event - general function to clean up of time event