@@ -549,18 +549,11 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
549549 }
550550}
551551
552- /*
553- * Explicit request to remove a time event. The removal of a time event needs to
554- * be synchronized with the flow of a time event's end notification, which also
555- * removes the time event from the op mode data structures.
556- */
557- void iwl_mvm_remove_time_event (struct iwl_mvm * mvm ,
558- struct iwl_mvm_vif * mvmvif ,
559- struct iwl_mvm_time_event_data * te_data )
552+ static bool __iwl_mvm_remove_time_event (struct iwl_mvm * mvm ,
553+ struct iwl_mvm_time_event_data * te_data ,
554+ u32 * uid )
560555{
561- struct iwl_time_event_cmd time_cmd = {};
562- u32 id , uid ;
563- int ret ;
556+ u32 id ;
564557
565558 /*
566559 * 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,
569562 spin_lock_bh (& mvm -> time_event_lock );
570563
571564 /* Save time event uid before clearing its data */
572- uid = te_data -> uid ;
565+ * uid = te_data -> uid ;
573566 id = te_data -> id ;
574567
575568 /*
@@ -584,10 +577,59 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
584577 * send a removal command.
585578 */
586579 if (id == TE_MAX ) {
587- IWL_DEBUG_TE (mvm , "TE 0x%x has already ended\n" , uid );
588- return ;
580+ IWL_DEBUG_TE (mvm , "TE 0x%x has already ended\n" , * uid );
581+ return false ;
589582 }
590583
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+ */
593+ static 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+ */
622+ void 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+
591633 /* When we remove a TE, the UID is to be set in the id field */
592634 time_cmd .id = cpu_to_le32 (uid );
593635 time_cmd .action = cpu_to_le32 (FW_CTXT_ACTION_REMOVE );
@@ -666,36 +708,59 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
666708 return iwl_mvm_time_event_send_add (mvm , vif , te_data , & time_cmd );
667709}
668710
669- void iwl_mvm_stop_p2p_roc (struct iwl_mvm * mvm )
711+ void iwl_mvm_stop_roc (struct iwl_mvm * mvm )
670712{
671713 struct iwl_mvm_vif * mvmvif ;
672714 struct iwl_mvm_time_event_data * te_data ;
715+ bool is_p2p = false;
673716
674717 lockdep_assert_held (& mvm -> mutex );
675718
719+ mvmvif = NULL ;
720+ spin_lock_bh (& mvm -> time_event_lock );
721+
676722 /*
677723 * Iterate over the list of time events and find the time event that is
678724 * associated with a P2P_DEVICE interface.
679725 * This assumes that a P2P_DEVICE interface can have only a single time
680726 * event at any given time and this time event coresponds to a ROC
681727 * request
682728 */
683- mvmvif = NULL ;
684- spin_lock_bh (& mvm -> time_event_lock );
685729 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 ) {
687732 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 ;
689749 }
690750 }
751+
752+ remove_te :
691753 spin_unlock_bh (& mvm -> time_event_lock );
692754
693755 if (!mvmvif ) {
694- IWL_WARN (mvm , "P2P_DEVICE no remain on channel event\n" );
756+ IWL_WARN (mvm , "No remain on channel event\n" );
695757 return ;
696758 }
697759
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 );
699764
700765 iwl_mvm_roc_finished (mvm );
701766}
0 commit comments