summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw89/ps.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/ps.c')
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index 84201ef19c17..917c01e5e9ed 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
+#include "chan.h"
#include "coex.h"
#include "core.h"
#include "debug.h"
@@ -257,8 +258,13 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
{
struct ieee80211_vif *vif, *found_vif = NULL;
struct rtw89_vif *rtwvif;
+ enum rtw89_entity_mode mode;
int count = 0;
+ mode = rtw89_get_entity_mode(rtwdev);
+ if (mode == RTW89_ENTITY_MODE_MCC)
+ goto disable_lps;
+
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
vif = rtwvif_to_vif(rtwvif);
@@ -273,8 +279,71 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
if (count == 1 && found_vif->cfg.ps) {
rtwdev->lps_enabled = true;
- } else {
- rtw89_leave_lps(rtwdev);
- rtwdev->lps_enabled = false;
+ return;
}
+
+disable_lps:
+ rtw89_leave_lps(rtwdev);
+ rtwdev->lps_enabled = false;
+}
+
+void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif)
+{
+ struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_ie *ie = &setter->ie;
+ struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
+ struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
+
+ if (setter->noa_count) {
+ setter->noa_index++;
+ setter->noa_count = 0;
+ }
+
+ memset(ie, 0, sizeof(*ie));
+
+ p2p_head->eid = WLAN_EID_VENDOR_SPECIFIC;
+ p2p_head->ie_len = 4 + sizeof(*noa_head);
+ p2p_head->oui[0] = (WLAN_OUI_WFA >> 16) & 0xff;
+ p2p_head->oui[1] = (WLAN_OUI_WFA >> 8) & 0xff;
+ p2p_head->oui[2] = (WLAN_OUI_WFA >> 0) & 0xff;
+ p2p_head->oui_type = WLAN_OUI_TYPE_WFA_P2P;
+
+ noa_head->attr_type = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
+ noa_head->attr_len = cpu_to_le16(2);
+ noa_head->index = setter->noa_index;
+ noa_head->oppps_ctwindow = 0;
+}
+
+void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif,
+ const struct ieee80211_p2p_noa_desc *desc)
+{
+ struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_ie *ie = &setter->ie;
+ struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
+ struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
+
+ if (!desc->count || !desc->duration)
+ return;
+
+ if (setter->noa_count >= RTW89_P2P_MAX_NOA_NUM)
+ return;
+
+ p2p_head->ie_len += sizeof(*desc);
+ le16_add_cpu(&noa_head->attr_len, sizeof(*desc));
+
+ ie->noa_desc[setter->noa_count++] = *desc;
+}
+
+u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data)
+{
+ struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa;
+ struct rtw89_p2p_noa_ie *ie = &setter->ie;
+ void *tail;
+
+ if (!setter->noa_count)
+ return 0;
+
+ *data = ie;
+ tail = ie->noa_desc + setter->noa_count;
+ return tail - *data;
}