You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
5.9 KiB
171 lines
5.9 KiB
1 year ago
|
From 5e16e95dd7bc9379701e4f3c9ca091ca19149c26 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
|
||
|
Date: Wed, 24 May 2023 15:00:30 +0200
|
||
|
Subject: [PATCH 067/142] wifi: rtw89: check if atomic before queuing c2h
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Bugzilla: https://bugzilla.redhat.com/2207499
|
||
|
|
||
|
commit 860e8263ae92667a2002163886fd2ebd8c67f699
|
||
|
Author: Zong-Zhe Yang <kevin_yang@realtek.com>
|
||
|
Date: Tue Nov 29 16:31:26 2022 +0800
|
||
|
|
||
|
wifi: rtw89: check if atomic before queuing c2h
|
||
|
|
||
|
Before queuing C2H work, we check atomicity of the C2H's handler first now.
|
||
|
If atomic or lock-free, handle it directly; otherwise, handle it with mutex
|
||
|
in work as previous. This prepares for MAC MCC C2Hs which require to be
|
||
|
processed directly. And, their handlers will be functions which can be
|
||
|
considered atomic.
|
||
|
|
||
|
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
|
||
|
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
|
||
|
Signed-off-by: Kalle Valo <kvalo@kernel.org>
|
||
|
Link: https://lore.kernel.org/r/20221129083130.45708-3-pkshih@realtek.com
|
||
|
|
||
|
Signed-off-by: Íñigo Huguet <ihuguet@redhat.com>
|
||
|
---
|
||
|
drivers/net/wireless/realtek/rtw89/fw.c | 47 +++++++++++++++++++++++++++++---
|
||
|
drivers/net/wireless/realtek/rtw89/fw.h | 14 ++++++++++
|
||
|
drivers/net/wireless/realtek/rtw89/mac.c | 10 +++++++
|
||
|
drivers/net/wireless/realtek/rtw89/mac.h | 1 +
|
||
|
4 files changed, 68 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
|
||
|
index 315f5c3a51dfc..ce71fc1a04a02 100644
|
||
|
--- a/drivers/net/wireless/realtek/rtw89/fw.c
|
||
|
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
|
||
|
@@ -11,6 +11,9 @@
|
||
|
#include "phy.h"
|
||
|
#include "reg.h"
|
||
|
|
||
|
+static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
|
||
|
+ struct sk_buff *skb);
|
||
|
+
|
||
|
static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
|
||
|
bool header)
|
||
|
{
|
||
|
@@ -2382,8 +2385,43 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev)
|
||
|
mutex_unlock(&rtwdev->mutex);
|
||
|
}
|
||
|
|
||
|
+static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h)
|
||
|
+{
|
||
|
+ struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h);
|
||
|
+
|
||
|
+ attr->category = RTW89_GET_C2H_CATEGORY(c2h->data);
|
||
|
+ attr->class = RTW89_GET_C2H_CLASS(c2h->data);
|
||
|
+ attr->func = RTW89_GET_C2H_FUNC(c2h->data);
|
||
|
+ attr->len = RTW89_GET_C2H_LEN(c2h->data);
|
||
|
+}
|
||
|
+
|
||
|
+static bool rtw89_fw_c2h_chk_atomic(struct rtw89_dev *rtwdev,
|
||
|
+ struct sk_buff *c2h)
|
||
|
+{
|
||
|
+ struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h);
|
||
|
+ u8 category = attr->category;
|
||
|
+ u8 class = attr->class;
|
||
|
+ u8 func = attr->func;
|
||
|
+
|
||
|
+ switch (category) {
|
||
|
+ default:
|
||
|
+ return false;
|
||
|
+ case RTW89_C2H_CAT_MAC:
|
||
|
+ return rtw89_mac_c2h_chk_atomic(rtwdev, class, func);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h)
|
||
|
{
|
||
|
+ rtw89_fw_c2h_parse_attr(c2h);
|
||
|
+ if (!rtw89_fw_c2h_chk_atomic(rtwdev, c2h))
|
||
|
+ goto enqueue;
|
||
|
+
|
||
|
+ rtw89_fw_c2h_cmd_handle(rtwdev, c2h);
|
||
|
+ dev_kfree_skb_any(c2h);
|
||
|
+ return;
|
||
|
+
|
||
|
+enqueue:
|
||
|
skb_queue_tail(&rtwdev->c2h_queue, c2h);
|
||
|
ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
|
||
|
}
|
||
|
@@ -2391,10 +2429,11 @@ void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h)
|
||
|
static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
|
||
|
struct sk_buff *skb)
|
||
|
{
|
||
|
- u8 category = RTW89_GET_C2H_CATEGORY(skb->data);
|
||
|
- u8 class = RTW89_GET_C2H_CLASS(skb->data);
|
||
|
- u8 func = RTW89_GET_C2H_FUNC(skb->data);
|
||
|
- u16 len = RTW89_GET_C2H_LEN(skb->data);
|
||
|
+ struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb);
|
||
|
+ u8 category = attr->category;
|
||
|
+ u8 class = attr->class;
|
||
|
+ u8 func = attr->func;
|
||
|
+ u16 len = attr->len;
|
||
|
bool dump = true;
|
||
|
|
||
|
if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
|
||
|
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
|
||
|
index 509a3eac5ffe3..d76d0c80f0256 100644
|
||
|
--- a/drivers/net/wireless/realtek/rtw89/fw.h
|
||
|
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
|
||
|
@@ -2778,6 +2778,20 @@ static inline void RTW89_SET_FWCMD_TSF32_TOGL_EARLY(void *cmd, u32 val)
|
||
|
#define RTW89_GET_C2H_LEN(c2h) \
|
||
|
le32_get_bits(*((const __le32 *)(c2h) + 1), GENMASK(13, 0))
|
||
|
|
||
|
+struct rtw89_fw_c2h_attr {
|
||
|
+ u8 category;
|
||
|
+ u8 class;
|
||
|
+ u8 func;
|
||
|
+ u16 len;
|
||
|
+};
|
||
|
+
|
||
|
+static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb)
|
||
|
+{
|
||
|
+ static_assert(sizeof(skb->cb) >= sizeof(struct rtw89_fw_c2h_attr));
|
||
|
+
|
||
|
+ return (struct rtw89_fw_c2h_attr *)skb->cb;
|
||
|
+}
|
||
|
+
|
||
|
#define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2)
|
||
|
#define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
|
||
|
index 6587cdf6ba624..098637a848953 100644
|
||
|
--- a/drivers/net/wireless/realtek/rtw89/mac.c
|
||
|
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
|
||
|
@@ -4208,6 +4208,16 @@ void (* const rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev,
|
||
|
[RTW89_MAC_C2H_FUNC_BCN_CNT] = rtw89_mac_c2h_bcn_cnt,
|
||
|
};
|
||
|
|
||
|
+bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
|
||
|
+{
|
||
|
+ switch (class) {
|
||
|
+ default:
|
||
|
+ return false;
|
||
|
+ case RTW89_MAC_C2H_CLASS_MCC:
|
||
|
+ return true;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
||
|
u32 len, u8 class, u8 func)
|
||
|
{
|
||
|
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
|
||
|
index 045e8ec61a41e..82b9e81fe4744 100644
|
||
|
--- a/drivers/net/wireless/realtek/rtw89/mac.h
|
||
|
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
|
||
|
@@ -894,6 +894,7 @@ static inline int rtw89_chip_disable_bb_rf(struct rtw89_dev *rtwdev)
|
||
|
|
||
|
u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev);
|
||
|
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err);
|
||
|
+bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func);
|
||
|
void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
|
||
|
u32 len, u8 class, u8 func);
|
||
|
int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev);
|
||
|
--
|
||
|
2.13.6
|
||
|
|