summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek')
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c25
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h10
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c17
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h4
5 files changed, 58 insertions, 1 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 00c56ab6306b..58f4e47aa96a 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -172,6 +172,17 @@ static void rtw_fw_bcn_filter_notify(struct rtw_dev *rtwdev, u8 *payload,
&dev_iter_data);
}
+static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload,
+ u8 length)
+{
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+ dm_info->scan_density = payload[0];
+
+ rtw_dbg(rtwdev, RTW_DBG_FW, "scan.density = %x\n",
+ dm_info->scan_density);
+}
+
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
{
struct rtw_c2h_cmd *c2h;
@@ -235,6 +246,10 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
case C2H_WLAN_RFON:
complete(&rtwdev->lps_leave_check);
break;
+ case C2H_SCAN_RESULT:
+ complete(&rtwdev->fw_scan_density);
+ rtw_fw_scan_result(rtwdev, c2h->payload, len);
+ break;
default:
/* pass offset for further operation */
*((u32 *)skb->cb) = pkt_offset;
@@ -1703,3 +1718,13 @@ void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable)
rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
}
+
+void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
+{
+ u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SCAN);
+ SET_SCAN_START(h2c_pkt, start);
+
+ rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 832ef2bfe5f9..a8a7162fbe64 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -30,6 +30,8 @@
#define BCN_FILTER_CONNECTED 2
#define BCN_FILTER_NOTIFY_BEACON_LOSS 3
+#define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10)
+
enum rtw_c2h_cmd_id {
C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09,
@@ -39,6 +41,7 @@ enum rtw_c2h_cmd_id {
C2H_WLAN_INFO = 0x27,
C2H_WLAN_RFON = 0x32,
C2H_BCN_FILTER_NOTIFY = 0x36,
+ C2H_SCAN_RESULT = 0x38,
C2H_HW_FEATURE_DUMP = 0xfd,
C2H_HALMAC = 0xff,
};
@@ -86,6 +89,7 @@ enum rtw_fw_feature {
FW_FEATURE_LCLK = BIT(2),
FW_FEATURE_PG = BIT(3),
FW_FEATURE_BCN_FILTER = BIT(5),
+ FW_FEATURE_NOTIFY_SCAN = BIT(6),
FW_FEATURE_MAX = BIT(31),
};
@@ -369,6 +373,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
#define H2C_CMD_BCN_FILTER_OFFLOAD_P1 0x57
#define H2C_CMD_WL_PHY_INFO 0x58
+#define H2C_CMD_SCAN 0x59
#define H2C_CMD_COEX_TDMA_TYPE 0x60
#define H2C_CMD_QUERY_BT_INFO 0x61
@@ -419,6 +424,9 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(13, 4))
+#define SET_SCAN_START(h2c_pkt, value) \
+ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+
#define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8))
#define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \
@@ -652,5 +660,5 @@ void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c);
void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev);
int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
u32 *buffer);
-
+void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 8f46b16c8d5d..8a180c95e7e6 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -605,6 +605,7 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
rtw_vif_port_config(rtwdev, rtwvif, config);
rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
+ rtw_core_fw_scan_notify(rtwdev, true);
set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
@@ -624,6 +625,8 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
+ rtw_core_fw_scan_notify(rtwdev, false);
+
ether_addr_copy(rtwvif->mac_addr, vif->addr);
config |= PORT_SET_MAC_ADDR;
rtw_vif_port_config(rtwdev, rtwvif, config);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index df115bb7fdf7..47f4838d0c58 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1185,6 +1185,22 @@ err:
return ret;
}
+void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
+{
+ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_NOTIFY_SCAN))
+ return;
+
+ if (start) {
+ rtw_fw_scan_notify(rtwdev, true);
+ } else {
+ reinit_completion(&rtwdev->fw_scan_density);
+ rtw_fw_scan_notify(rtwdev, false);
+ if (!wait_for_completion_timeout(&rtwdev->fw_scan_density,
+ SCAN_NOTIFY_TIMEOUT))
+ rtw_warn(rtwdev, "firmware failed to report density after scan\n");
+ }
+}
+
int rtw_core_start(struct rtw_dev *rtwdev)
{
int ret;
@@ -1763,6 +1779,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
init_waitqueue_head(&rtwdev->coex.wait);
init_completion(&rtwdev->lps_leave_check);
+ init_completion(&rtwdev->fw_scan_density);
rtwdev->sec.total_cam_num = 32;
rtwdev->hal.current_channel = 1;
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 02ad175055cb..20b20a6db9cc 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1620,6 +1620,8 @@ struct rtw_dm_info {
struct rtw_iqk_info iqk;
struct rtw_gapk_info gapk;
bool is_bt_iqk_timeout;
+
+ u8 scan_density;
};
struct rtw_efuse {
@@ -1869,6 +1871,7 @@ struct rtw_dev {
struct rtw_wow_param wow;
bool need_rfk;
+ struct completion fw_scan_density;
/* hci related data, must be last */
u8 priv[] __aligned(sizeof(void *));
@@ -1974,6 +1977,7 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
bool fw_exist);
void rtw_fw_recovery(struct rtw_dev *rtwdev);
+void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
const char *prefix_str);
int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size,