@@ -641,11 +641,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
641641 }
642642}
643643
644+ static void iwl_mvm_cancel_session_protection (struct iwl_mvm * mvm ,
645+ struct iwl_mvm_vif * mvmvif )
646+ {
647+ struct iwl_mvm_session_prot_cmd cmd = {
648+ .id_and_color =
649+ cpu_to_le32 (FW_CMD_ID_AND_COLOR (mvmvif -> id ,
650+ mvmvif -> color )),
651+ .action = cpu_to_le32 (FW_CTXT_ACTION_REMOVE ),
652+ .conf_id = cpu_to_le32 (mvmvif -> time_event_data .id ),
653+ };
654+ int ret ;
655+
656+ ret = iwl_mvm_send_cmd_pdu (mvm , iwl_cmd_id (SESSION_PROTECTION_CMD ,
657+ MAC_CONF_GROUP , 0 ),
658+ 0 , sizeof (cmd ), & cmd );
659+ if (ret )
660+ IWL_ERR (mvm ,
661+ "Couldn't send the SESSION_PROTECTION_CMD: %d\n" , ret );
662+ }
663+
644664static bool __iwl_mvm_remove_time_event (struct iwl_mvm * mvm ,
645665 struct iwl_mvm_time_event_data * te_data ,
646666 u32 * uid )
647667{
648668 u32 id ;
669+ struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (te_data -> vif );
649670
650671 /*
651672 * It is possible that by the time we got to this point the time
@@ -663,14 +684,29 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
663684 iwl_mvm_te_clear_data (mvm , te_data );
664685 spin_unlock_bh (& mvm -> time_event_lock );
665686
666- /*
667- * It is possible that by the time we try to remove it, the time event
668- * has already ended and removed. In such a case there is no need to
669- * send a removal command.
687+ /* When session protection is supported, the te_data->id field
688+ * is reused to save session protection's configuration.
670689 */
671- if (id == TE_MAX ) {
672- IWL_DEBUG_TE (mvm , "TE 0x%x has already ended\n" , * uid );
690+ if (fw_has_capa (& mvm -> fw -> ucode_capa ,
691+ IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD )) {
692+ if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID ) {
693+ /* Session protection is still ongoing. Cancel it */
694+ iwl_mvm_cancel_session_protection (mvm , mvmvif );
695+ if (te_data -> vif -> type == NL80211_IFTYPE_P2P_DEVICE ) {
696+ set_bit (IWL_MVM_STATUS_NEED_FLUSH_P2P , & mvm -> status );
697+ iwl_mvm_roc_finished (mvm );
698+ }
699+ }
673700 return false;
701+ } else {
702+ /* It is possible that by the time we try to remove it, the
703+ * time event has already ended and removed. In such a case
704+ * there is no need to send a removal command.
705+ */
706+ if (id == TE_MAX ) {
707+ IWL_DEBUG_TE (mvm , "TE 0x%x has already ended\n" , * uid );
708+ return false;
709+ }
674710 }
675711
676712 return true;
@@ -771,6 +807,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
771807 struct iwl_rx_packet * pkt = rxb_addr (rxb );
772808 struct iwl_mvm_session_prot_notif * notif = (void * )pkt -> data ;
773809 struct ieee80211_vif * vif ;
810+ struct iwl_mvm_vif * mvmvif ;
774811
775812 rcu_read_lock ();
776813 vif = iwl_mvm_rcu_dereference_vif_id (mvm , le32_to_cpu (notif -> mac_id ),
@@ -779,9 +816,10 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
779816 if (!vif )
780817 goto out_unlock ;
781818
819+ mvmvif = iwl_mvm_vif_from_mac80211 (vif );
820+
782821 /* The vif is not a P2P_DEVICE, maintain its time_event_data */
783822 if (vif -> type != NL80211_IFTYPE_P2P_DEVICE ) {
784- struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
785823 struct iwl_mvm_time_event_data * te_data =
786824 & mvmvif -> time_event_data ;
787825
@@ -816,10 +854,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
816854
817855 if (!le32_to_cpu (notif -> status ) || !le32_to_cpu (notif -> start )) {
818856 /* End TE, notify mac80211 */
857+ mvmvif -> time_event_data .id = SESSION_PROTECT_CONF_MAX_ID ;
819858 ieee80211_remain_on_channel_expired (mvm -> hw );
820859 set_bit (IWL_MVM_STATUS_NEED_FLUSH_P2P , & mvm -> status );
821860 iwl_mvm_roc_finished (mvm );
822861 } else if (le32_to_cpu (notif -> start )) {
862+ if (WARN_ON (mvmvif -> time_event_data .id !=
863+ le32_to_cpu (notif -> conf_id )))
864+ goto out_unlock ;
823865 set_bit (IWL_MVM_STATUS_ROC_RUNNING , & mvm -> status );
824866 ieee80211_ready_on_channel (mvm -> hw ); /* Start TE */
825867 }
@@ -845,20 +887,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
845887
846888 lockdep_assert_held (& mvm -> mutex );
847889
890+ /* The time_event_data.id field is reused to save session
891+ * protection's configuration.
892+ */
848893 switch (type ) {
849894 case IEEE80211_ROC_TYPE_NORMAL :
850- cmd . conf_id =
851- cpu_to_le32 ( SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV ) ;
895+ mvmvif -> time_event_data . id =
896+ SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV ;
852897 break ;
853898 case IEEE80211_ROC_TYPE_MGMT_TX :
854- cmd . conf_id =
855- cpu_to_le32 ( SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION ) ;
899+ mvmvif -> time_event_data . id =
900+ SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION ;
856901 break ;
857902 default :
858903 WARN_ONCE (1 , "Got an invalid ROC type\n" );
859904 return - EINVAL ;
860905 }
861906
907+ cmd .conf_id = cpu_to_le32 (mvmvif -> time_event_data .id );
862908 return iwl_mvm_send_cmd_pdu (mvm , iwl_cmd_id (SESSION_PROTECTION_CMD ,
863909 MAC_CONF_GROUP , 0 ),
864910 0 , sizeof (cmd ), & cmd );
@@ -960,25 +1006,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm)
9601006 __iwl_mvm_remove_time_event (mvm , te_data , & uid );
9611007}
9621008
963- static void iwl_mvm_cancel_session_protection (struct iwl_mvm * mvm ,
964- struct iwl_mvm_vif * mvmvif )
965- {
966- struct iwl_mvm_session_prot_cmd cmd = {
967- .id_and_color =
968- cpu_to_le32 (FW_CMD_ID_AND_COLOR (mvmvif -> id ,
969- mvmvif -> color )),
970- .action = cpu_to_le32 (FW_CTXT_ACTION_REMOVE ),
971- };
972- int ret ;
973-
974- ret = iwl_mvm_send_cmd_pdu (mvm , iwl_cmd_id (SESSION_PROTECTION_CMD ,
975- MAC_CONF_GROUP , 0 ),
976- 0 , sizeof (cmd ), & cmd );
977- if (ret )
978- IWL_ERR (mvm ,
979- "Couldn't send the SESSION_PROTECTION_CMD: %d\n" , ret );
980- }
981-
9821009void iwl_mvm_stop_roc (struct iwl_mvm * mvm , struct ieee80211_vif * vif )
9831010{
9841011 struct iwl_mvm_vif * mvmvif ;
@@ -988,10 +1015,13 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
9881015 IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD )) {
9891016 mvmvif = iwl_mvm_vif_from_mac80211 (vif );
9901017
991- iwl_mvm_cancel_session_protection (mvm , mvmvif );
992-
993- if (vif -> type == NL80211_IFTYPE_P2P_DEVICE )
1018+ if (vif -> type == NL80211_IFTYPE_P2P_DEVICE ) {
1019+ iwl_mvm_cancel_session_protection (mvm , mvmvif );
9941020 set_bit (IWL_MVM_STATUS_NEED_FLUSH_P2P , & mvm -> status );
1021+ } else {
1022+ iwl_mvm_remove_aux_roc_te (mvm , mvmvif ,
1023+ & mvmvif -> time_event_data );
1024+ }
9951025
9961026 iwl_mvm_roc_finished (mvm );
9971027
@@ -1126,10 +1156,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
11261156 cpu_to_le32 (FW_CMD_ID_AND_COLOR (mvmvif -> id ,
11271157 mvmvif -> color )),
11281158 .action = cpu_to_le32 (FW_CTXT_ACTION_ADD ),
1129- .conf_id = cpu_to_le32 (SESSION_PROTECT_CONF_ASSOC ),
11301159 .duration_tu = cpu_to_le32 (MSEC_TO_TU (duration )),
11311160 };
11321161
1162+ /* The time_event_data.id field is reused to save session
1163+ * protection's configuration.
1164+ */
1165+ mvmvif -> time_event_data .id = SESSION_PROTECT_CONF_ASSOC ;
1166+ cmd .conf_id = cpu_to_le32 (mvmvif -> time_event_data .id );
1167+
11331168 lockdep_assert_held (& mvm -> mutex );
11341169
11351170 spin_lock_bh (& mvm -> time_event_lock );
0 commit comments