Commit 1cf260e3 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Kalle Valo

iwlwifi: mvm: properly cancel a session protection for P2P

We need to feed the configuration id to remove  session protection
properly.
Remember the conf_id when we add the session protection so that we
can give it back when we want to remove the session protection.
While at it, slightly improve the kernel doc for the conf_id
of the notification.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Fixes: fe959c7b ("iwlwifi: mvm: use the new session protection command")
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20201107104557.3642f730333d.I01a98ecde62096d00d171cf34ad775bf80cb0277@changeid
parent fb8d1b6e
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation * Copyright(c) 2018 - 2020 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation * Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -421,12 +421,14 @@ struct iwl_hs20_roc_res { ...@@ -421,12 +421,14 @@ struct iwl_hs20_roc_res {
* able to run the GO Negotiation. Will not be fragmented and not * able to run the GO Negotiation. Will not be fragmented and not
* repetitive. Valid only on the P2P Device MAC. Only the duration will * repetitive. Valid only on the P2P Device MAC. Only the duration will
* be taken into account. * be taken into account.
* @SESSION_PROTECT_CONF_MAX_ID: not used
*/ */
enum iwl_mvm_session_prot_conf_id { enum iwl_mvm_session_prot_conf_id {
SESSION_PROTECT_CONF_ASSOC, SESSION_PROTECT_CONF_ASSOC,
SESSION_PROTECT_CONF_GO_CLIENT_ASSOC, SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV, SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION, SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION,
SESSION_PROTECT_CONF_MAX_ID,
}; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */ }; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
/** /**
...@@ -459,7 +461,7 @@ struct iwl_mvm_session_prot_cmd { ...@@ -459,7 +461,7 @@ struct iwl_mvm_session_prot_cmd {
* @mac_id: the mac id for which the session protection started / ended * @mac_id: the mac id for which the session protection started / ended
* @status: 1 means success, 0 means failure * @status: 1 means success, 0 means failure
* @start: 1 means the session protection started, 0 means it ended * @start: 1 means the session protection started, 0 means it ended
* @conf_id: the configuration id of the session that started / eneded * @conf_id: see &enum iwl_mvm_session_prot_conf_id
* *
* Note that any session protection will always get two notifications: start * Note that any session protection will always get two notifications: start
* and end even the firmware could not schedule it. * and end even the firmware could not schedule it.
......
...@@ -641,11 +641,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, ...@@ -641,11 +641,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
} }
} }
static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif)
{
struct iwl_mvm_session_prot_cmd cmd = {
.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color)),
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
.conf_id = cpu_to_le32(mvmvif->time_event_data.id),
};
int ret;
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(mvm,
"Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
}
static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
struct iwl_mvm_time_event_data *te_data, struct iwl_mvm_time_event_data *te_data,
u32 *uid) u32 *uid)
{ {
u32 id; u32 id;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
/* /*
* It is possible that by the time we got to this point the time * 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, ...@@ -663,14 +684,29 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
iwl_mvm_te_clear_data(mvm, te_data); iwl_mvm_te_clear_data(mvm, te_data);
spin_unlock_bh(&mvm->time_event_lock); spin_unlock_bh(&mvm->time_event_lock);
/* /* When session protection is supported, the te_data->id field
* It is possible that by the time we try to remove it, the time event * is reused to save session protection's configuration.
* has already ended and removed. In such a case there is no need to
* send a removal command.
*/ */
if (id == TE_MAX) { if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) {
/* Session protection is still ongoing. Cancel it */
iwl_mvm_cancel_session_protection(mvm, mvmvif);
if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
iwl_mvm_roc_finished(mvm);
}
}
return false; return false;
} else {
/* It is possible that by the time we try to remove it, the
* time event has already ended and removed. In such a case
* there is no need to send a removal command.
*/
if (id == TE_MAX) {
IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
return false;
}
} }
return true; return true;
...@@ -771,6 +807,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, ...@@ -771,6 +807,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data; struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct iwl_mvm_vif *mvmvif;
rcu_read_lock(); rcu_read_lock();
vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id), 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, ...@@ -779,9 +816,10 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
if (!vif) if (!vif)
goto out_unlock; goto out_unlock;
mvmvif = iwl_mvm_vif_from_mac80211(vif);
/* The vif is not a P2P_DEVICE, maintain its time_event_data */ /* The vif is not a P2P_DEVICE, maintain its time_event_data */
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = struct iwl_mvm_time_event_data *te_data =
&mvmvif->time_event_data; &mvmvif->time_event_data;
...@@ -816,10 +854,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, ...@@ -816,10 +854,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) { if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
/* End TE, notify mac80211 */ /* End TE, notify mac80211 */
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID;
ieee80211_remain_on_channel_expired(mvm->hw); ieee80211_remain_on_channel_expired(mvm->hw);
set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
iwl_mvm_roc_finished(mvm); iwl_mvm_roc_finished(mvm);
} else if (le32_to_cpu(notif->start)) { } else if (le32_to_cpu(notif->start)) {
if (WARN_ON(mvmvif->time_event_data.id !=
le32_to_cpu(notif->conf_id)))
goto out_unlock;
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
ieee80211_ready_on_channel(mvm->hw); /* Start TE */ ieee80211_ready_on_channel(mvm->hw); /* Start TE */
} }
...@@ -845,20 +887,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm, ...@@ -845,20 +887,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* The time_event_data.id field is reused to save session
* protection's configuration.
*/
switch (type) { switch (type) {
case IEEE80211_ROC_TYPE_NORMAL: case IEEE80211_ROC_TYPE_NORMAL:
cmd.conf_id = mvmvif->time_event_data.id =
cpu_to_le32(SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV); SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV;
break; break;
case IEEE80211_ROC_TYPE_MGMT_TX: case IEEE80211_ROC_TYPE_MGMT_TX:
cmd.conf_id = mvmvif->time_event_data.id =
cpu_to_le32(SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION); SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION;
break; break;
default: default:
WARN_ONCE(1, "Got an invalid ROC type\n"); WARN_ONCE(1, "Got an invalid ROC type\n");
return -EINVAL; return -EINVAL;
} }
cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0), MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd); 0, sizeof(cmd), &cmd);
...@@ -960,25 +1006,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm) ...@@ -960,25 +1006,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm)
__iwl_mvm_remove_time_event(mvm, te_data, &uid); __iwl_mvm_remove_time_event(mvm, te_data, &uid);
} }
static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif)
{
struct iwl_mvm_session_prot_cmd cmd = {
.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color)),
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
};
int ret;
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
MAC_CONF_GROUP, 0),
0, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(mvm,
"Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
}
void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{ {
struct iwl_mvm_vif *mvmvif; struct iwl_mvm_vif *mvmvif;
...@@ -1129,10 +1156,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, ...@@ -1129,10 +1156,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color)), mvmvif->color)),
.action = cpu_to_le32(FW_CTXT_ACTION_ADD), .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
}; };
/* The time_event_data.id field is reused to save session
* protection's configuration.
*/
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC;
cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock); spin_lock_bh(&mvm->time_event_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment