Commit 10d162b2 authored by Po-Hao Huang's avatar Po-Hao Huang Committed by Kalle Valo

rtw88: 8822c: add ieee80211_ops::hw_scan

Declare this function allows us to use customized scanning policy.
By doing so we can be more time efficient on each scan. In order to
make existing coex mechanism work as usual, firmware notifies driver
on each channel switch event, then decide antenna ownership based on
the current channel/band. Do note that this new mechanism affects
throughput more than the sw_scan we used to have, but the overall
average throughput is not affected since each scan take less time.
Since the firmware size is limited, we only support probe requests
with custom IEs length under 128 bytes for now, if any user space
tools requires more than that, we'll introduce related changes
afterwards. For backward compatibility, we fallback to sw_scan when
using older firmware that does not support this feature.
Signed-off-by: default avatarPo-Hao Huang <phhuang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20211221085010.39421-1-pkshih@realtek.com
parent bc11517b
...@@ -22,6 +22,7 @@ enum rtw_debug_mask { ...@@ -22,6 +22,7 @@ enum rtw_debug_mask {
RTW_DBG_CFO = 0x00002000, RTW_DBG_CFO = 0x00002000,
RTW_DBG_PATH_DIV = 0x00004000, RTW_DBG_PATH_DIV = 0x00004000,
RTW_DBG_ADAPTIVITY = 0x00008000, RTW_DBG_ADAPTIVITY = 0x00008000,
RTW_DBG_HW_SCAN = 0x00010000,
RTW_DBG_ALL = 0xffffffff RTW_DBG_ALL = 0xffffffff
}; };
......
This diff is collapsed.
...@@ -32,6 +32,17 @@ ...@@ -32,6 +32,17 @@
#define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10) #define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10)
#define RTW_CHANNEL_TIME 45
#define RTW_OFF_CHAN_TIME 100
#define RTW_PASS_CHAN_TIME 105
#define RTW_DFS_CHAN_TIME 20
#define RTW_CH_INFO_SIZE 4
#define RTW_EX_CH_INFO_SIZE 3
#define RTW_EX_CH_INFO_HDR_SIZE 2
#define RTW_SCAN_WIDTH 0
#define RTW_PRI_CH_IDX 1
#define RTW_PROBE_PG_CNT 2
enum rtw_c2h_cmd_id { enum rtw_c2h_cmd_id {
C2H_CCX_TX_RPT = 0x03, C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09, C2H_BT_INFO = 0x09,
...@@ -48,7 +59,9 @@ enum rtw_c2h_cmd_id { ...@@ -48,7 +59,9 @@ enum rtw_c2h_cmd_id {
}; };
enum rtw_c2h_cmd_id_ext { enum rtw_c2h_cmd_id_ext {
C2H_SCAN_STATUS_RPT = 0x3,
C2H_CCX_RPT = 0x0f, C2H_CCX_RPT = 0x0f,
C2H_CHAN_SWITCH = 0x22,
}; };
struct rtw_c2h_cmd { struct rtw_c2h_cmd {
...@@ -101,6 +114,7 @@ enum rtw_fw_feature { ...@@ -101,6 +114,7 @@ enum rtw_fw_feature {
FW_FEATURE_BCN_FILTER = BIT(5), FW_FEATURE_BCN_FILTER = BIT(5),
FW_FEATURE_NOTIFY_SCAN = BIT(6), FW_FEATURE_NOTIFY_SCAN = BIT(6),
FW_FEATURE_ADAPTIVITY = BIT(7), FW_FEATURE_ADAPTIVITY = BIT(7),
FW_FEATURE_SCAN_OFFLOAD = BIT(8),
FW_FEATURE_MAX = BIT(31), FW_FEATURE_MAX = BIT(31),
}; };
...@@ -196,6 +210,51 @@ struct rtw_fw_wow_disconnect_para { ...@@ -196,6 +210,51 @@ struct rtw_fw_wow_disconnect_para {
u8 retry_count; u8 retry_count;
}; };
enum rtw_channel_type {
RTW_CHANNEL_PASSIVE,
RTW_CHANNEL_ACTIVE,
RTW_CHANNEL_RADAR,
};
enum rtw_scan_extra_id {
RTW_SCAN_EXTRA_ID_DFS,
};
enum rtw_scan_extra_info {
RTW_SCAN_EXTRA_ACTION_SCAN,
};
enum rtw_scan_report_code {
RTW_SCAN_REPORT_SUCCESS = 0x00,
RTW_SCAN_REPORT_ERR_PHYDM = 0x01,
RTW_SCAN_REPORT_ERR_ID = 0x02,
RTW_SCAN_REPORT_ERR_TX = 0x03,
RTW_SCAN_REPORT_CANCELED = 0x10,
RTW_SCAN_REPORT_CANCELED_EXT = 0x11,
RTW_SCAN_REPORT_FW_DISABLED = 0xF0,
};
enum rtw_scan_notify_id {
RTW_SCAN_NOTIFY_ID_PRESWITCH = 0x00,
RTW_SCAN_NOTIFY_ID_POSTSWITCH = 0x01,
RTW_SCAN_NOTIFY_ID_PROBE_PRETX = 0x02,
RTW_SCAN_NOTIFY_ID_PROBE_ISSUETX = 0x03,
RTW_SCAN_NOTIFY_ID_NULL0_PRETX = 0x04,
RTW_SCAN_NOTIFY_ID_NULL0_ISSUETX = 0x05,
RTW_SCAN_NOTIFY_ID_NULL0_POSTTX = 0x06,
RTW_SCAN_NOTIFY_ID_NULL1_PRETX = 0x07,
RTW_SCAN_NOTIFY_ID_NULL1_ISSUETX = 0x08,
RTW_SCAN_NOTIFY_ID_NULL1_POSTTX = 0x09,
RTW_SCAN_NOTIFY_ID_DWELLEXT = 0x0A,
};
enum rtw_scan_notify_status {
RTW_SCAN_NOTIFY_STATUS_SUCCESS = 0x00,
RTW_SCAN_NOTIFY_STATUS_FAILURE = 0x01,
RTW_SCAN_NOTIFY_STATUS_RESOURCE = 0x02,
RTW_SCAN_NOTIFY_STATUS_TIMEOUT = 0x03,
};
struct rtw_ch_switch_option { struct rtw_ch_switch_option {
u8 periodic_option; u8 periodic_option;
u32 tsf_high; u32 tsf_high;
...@@ -209,6 +268,8 @@ struct rtw_ch_switch_option { ...@@ -209,6 +268,8 @@ struct rtw_ch_switch_option {
u8 slow_period; u8 slow_period;
u8 slow_period_sel; u8 slow_period_sel;
u8 nlo_en; u8 nlo_en;
bool switch_en;
bool back_op_en;
}; };
struct rtw_fw_hdr { struct rtw_fw_hdr {
...@@ -265,6 +326,11 @@ struct rtw_fw_hdr_legacy { ...@@ -265,6 +326,11 @@ struct rtw_fw_hdr_legacy {
#define GET_CCX_REPORT_SEQNUM_V1(c2h_payload) (c2h_payload[8] & 0xfc) #define GET_CCX_REPORT_SEQNUM_V1(c2h_payload) (c2h_payload[8] & 0xfc)
#define GET_CCX_REPORT_STATUS_V1(c2h_payload) (c2h_payload[9] & 0xc0) #define GET_CCX_REPORT_STATUS_V1(c2h_payload) (c2h_payload[9] & 0xc0)
#define GET_SCAN_REPORT_RETURN_CODE(c2h_payload) (c2h_payload[2] & 0xff)
#define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload) (c2h_payload[2])
#define GET_CHAN_SWITCH_ID(c2h_payload) (c2h_payload[3])
#define GET_CHAN_SWITCH_STATUS(c2h_payload) (c2h_payload[4])
#define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f) #define GET_RA_REPORT_RATE(c2h_payload) (c2h_payload[0] & 0x7f)
#define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7) #define GET_RA_REPORT_SGI(c2h_payload) ((c2h_payload[0] & 0x80) >> 7)
#define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6]) #define GET_RA_REPORT_BW(c2h_payload) (c2h_payload[6])
...@@ -284,6 +350,7 @@ struct rtw_fw_hdr_legacy { ...@@ -284,6 +350,7 @@ struct rtw_fw_hdr_legacy {
#define H2C_PKT_CH_SWITCH 0x02 #define H2C_PKT_CH_SWITCH 0x02
#define H2C_PKT_UPDATE_PKT 0x0C #define H2C_PKT_UPDATE_PKT 0x0C
#define H2C_PKT_SCAN_OFFLOAD 0x19
#define H2C_PKT_CH_SWITCH_LEN 0x20 #define H2C_PKT_CH_SWITCH_LEN 0x20
#define H2C_PKT_UPDATE_PKT_LEN 0x4 #define H2C_PKT_UPDATE_PKT_LEN 0x4
...@@ -334,6 +401,30 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) ...@@ -334,6 +401,30 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16)) le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16))
#define CHSW_INFO_SET_ACTION_ID(pkt, value) \ #define CHSW_INFO_SET_ACTION_ID(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24)) le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24))
#define CHSW_INFO_SET_EXTRA_INFO(pkt, value) \
le32p_replace_bits((__le32 *)(pkt) + 0x00, value, BIT(31))
#define CH_INFO_SET_CH(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x00, value, GENMASK(7, 0))
#define CH_INFO_SET_PRI_CH_IDX(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(3, 0))
#define CH_INFO_SET_BW(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x01, value, GENMASK(7, 4))
#define CH_INFO_SET_TIMEOUT(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x02, value, GENMASK(7, 0))
#define CH_INFO_SET_ACTION_ID(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x03, value, GENMASK(6, 0))
#define CH_INFO_SET_EXTRA_INFO(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x03, value, BIT(7))
#define EXTRA_CH_INFO_SET_ID(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x04, value, GENMASK(6, 0))
#define EXTRA_CH_INFO_SET_INFO(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x04, value, BIT(7))
#define EXTRA_CH_INFO_SET_SIZE(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x05, value, GENMASK(7, 0))
#define EXTRA_CH_INFO_SET_DFS_EXT_TIME(pkt, value) \
u8p_replace_bits((u8 *)(pkt) + 0x06, value, GENMASK(7, 0))
#define UPDATE_PKT_SET_SIZE(h2c_pkt, value) \ #define UPDATE_PKT_SET_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0))
...@@ -350,12 +441,18 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) ...@@ -350,12 +441,18 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2))
#define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value) \ #define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3))
#define CH_SWITCH_SET_SCAN_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(5))
#define CH_SWITCH_SET_BACK_OP_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(6))
#define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value) \ #define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
#define CH_SWITCH_SET_CH_NUM(h2c_pkt, value) \ #define CH_SWITCH_SET_CH_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
#define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value) \ #define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24))
#define CH_SWITCH_SET_DEST_BW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28))
#define CH_SWITCH_SET_DEST_CH(h2c_pkt, value) \ #define CH_SWITCH_SET_DEST_CH(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0))
#define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value) \ #define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value) \
...@@ -375,6 +472,41 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) ...@@ -375,6 +472,41 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value) \ #define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0)) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0))
#define SCAN_OFFLOAD_SET_START(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
#define SCAN_OFFLOAD_SET_BACK_OP_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
#define SCAN_OFFLOAD_SET_RANDOM_SEQ_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2))
#define SCAN_OFFLOAD_SET_NO_CCK_EN(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(3))
#define SCAN_OFFLOAD_SET_VERBOSE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(4))
#define SCAN_OFFLOAD_SET_CH_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
#define SCAN_OFFLOAD_SET_CH_INFO_SIZE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 16))
#define SCAN_OFFLOAD_SET_CH_INFO_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0))
#define SCAN_OFFLOAD_SET_OP_CH(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 8))
#define SCAN_OFFLOAD_SET_OP_PRI_CH_IDX(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(19, 16))
#define SCAN_OFFLOAD_SET_OP_BW(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 20))
#define SCAN_OFFLOAD_SET_OP_PORT_ID(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(26, 24))
#define SCAN_OFFLOAD_SET_OP_DWELL_TIME(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(15, 0))
#define SCAN_OFFLOAD_SET_OP_GAP_TIME(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 16))
#define SCAN_OFFLOAD_SET_MODE(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(3, 0))
#define SCAN_OFFLOAD_SET_SSID_NUM(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(7, 4))
#define SCAN_OFFLOAD_SET_PKT_LOC(h2c_pkt, value) \
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(15, 8))
/* Command H2C */ /* Command H2C */
#define H2C_CMD_RSVD_PAGE 0x0 #define H2C_CMD_RSVD_PAGE 0x0
#define H2C_CMD_MEDIA_STATUS_RPT 0x01 #define H2C_CMD_MEDIA_STATUS_RPT 0x01
...@@ -686,4 +818,14 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, ...@@ -686,4 +818,14 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
u32 *buffer); u32 *buffer);
void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start); void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
void rtw_fw_adaptivity(struct rtw_dev *rtwdev); void rtw_fw_adaptivity(struct rtw_dev *rtwdev);
void rtw_store_op_chan(struct rtw_dev *rtwdev);
void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool aborted);
int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool enable);
void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
#endif #endif
...@@ -161,6 +161,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, ...@@ -161,6 +161,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
rtwvif->stats.rx_unicast = 0; rtwvif->stats.rx_unicast = 0;
rtwvif->stats.tx_cnt = 0; rtwvif->stats.tx_cnt = 0;
rtwvif->stats.rx_cnt = 0; rtwvif->stats.rx_cnt = 0;
rtwvif->scan_req = NULL;
memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee)); memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
rtwvif->conf = &rtw_vif_port[port]; rtwvif->conf = &rtw_vif_port[port];
rtw_txq_init(rtwdev, vif->txq); rtw_txq_init(rtwdev, vif->txq);
...@@ -372,9 +373,15 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, ...@@ -372,9 +373,15 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_coex_media_status_notify(rtwdev, conf->assoc); rtw_coex_media_status_notify(rtwdev, conf->assoc);
if (rtw_bf_support) if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf); rtw_bf_assoc(rtwdev, vif, conf);
rtw_store_op_chan(rtwdev);
} else { } else {
rtw_leave_lps(rtwdev); rtw_leave_lps(rtwdev);
rtw_bf_disassoc(rtwdev, vif, conf); rtw_bf_disassoc(rtwdev, vif, conf);
/* Abort ongoing scan if cancel_scan isn't issued
* when disconnected by peer
*/
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
rtw_hw_scan_abort(rtwdev, vif);
} }
config |= PORT_SET_NET_TYPE; config |= PORT_SET_NET_TYPE;
...@@ -594,22 +601,9 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, ...@@ -594,22 +601,9 @@ static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
{ {
struct rtw_dev *rtwdev = hw->priv; struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = 0;
mutex_lock(&rtwdev->mutex); mutex_lock(&rtwdev->mutex);
rtw_core_scan_start(rtwdev, rtwvif, mac_addr, false);
rtw_leave_lps(rtwdev);
ether_addr_copy(rtwvif->mac_addr, mac_addr);
config |= PORT_SET_MAC_ADDR;
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);
mutex_unlock(&rtwdev->mutex); mutex_unlock(&rtwdev->mutex);
} }
...@@ -617,22 +611,9 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, ...@@ -617,22 +611,9 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct rtw_dev *rtwdev = hw->priv; struct rtw_dev *rtwdev = hw->priv;
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = 0;
mutex_lock(&rtwdev->mutex); mutex_lock(&rtwdev->mutex);
rtw_core_scan_complete(rtwdev, vif);
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);
rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
mutex_unlock(&rtwdev->mutex); mutex_unlock(&rtwdev->mutex);
} }
...@@ -815,6 +796,46 @@ static void rtw_reconfig_complete(struct ieee80211_hw *hw, ...@@ -815,6 +796,46 @@ static void rtw_reconfig_complete(struct ieee80211_hw *hw,
mutex_unlock(&rtwdev->mutex); mutex_unlock(&rtwdev->mutex);
} }
static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req)
{
struct rtw_dev *rtwdev = hw->priv;
int ret;
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
return 1;
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
return -EBUSY;
mutex_lock(&rtwdev->mutex);
rtw_hw_scan_start(rtwdev, vif, req);
ret = rtw_hw_scan_offload(rtwdev, vif, true);
if (ret) {
rtw_hw_scan_abort(rtwdev, vif);
rtw_err(rtwdev, "HW scan failed with status: %d\n", ret);
}
mutex_unlock(&rtwdev->mutex);
return ret;
}
static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rtw_dev *rtwdev = hw->priv;
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
return;
if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
return;
mutex_lock(&rtwdev->mutex);
rtw_hw_scan_abort(rtwdev, vif);
mutex_unlock(&rtwdev->mutex);
}
const struct ieee80211_ops rtw_ops = { const struct ieee80211_ops rtw_ops = {
.tx = rtw_ops_tx, .tx = rtw_ops_tx,
.wake_tx_queue = rtw_ops_wake_tx_queue, .wake_tx_queue = rtw_ops_wake_tx_queue,
...@@ -842,6 +863,8 @@ const struct ieee80211_ops rtw_ops = { ...@@ -842,6 +863,8 @@ const struct ieee80211_ops rtw_ops = {
.set_antenna = rtw_ops_set_antenna, .set_antenna = rtw_ops_set_antenna,
.get_antenna = rtw_ops_get_antenna, .get_antenna = rtw_ops_get_antenna,
.reconfig_complete = rtw_reconfig_complete, .reconfig_complete = rtw_reconfig_complete,
.hw_scan = rtw_ops_hw_scan,
.cancel_hw_scan = rtw_ops_cancel_hw_scan,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = rtw_ops_suspend, .suspend = rtw_ops_suspend,
.resume = rtw_ops_resume, .resume = rtw_ops_resume,
......
...@@ -637,6 +637,19 @@ static void rtw_txq_ba_work(struct work_struct *work) ...@@ -637,6 +637,19 @@ static void rtw_txq_ba_work(struct work_struct *work)
rtw_iterate_stas_atomic(rtwdev, rtw_txq_ba_iter, &data); rtw_iterate_stas_atomic(rtwdev, rtw_txq_ba_iter, &data);
} }
void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel)
{
if (IS_CH_2G_BAND(channel))
pkt_stat->band = NL80211_BAND_2GHZ;
else if (IS_CH_5G_BAND(channel))
pkt_stat->band = NL80211_BAND_5GHZ;
else
return;
pkt_stat->freq = ieee80211_channel_to_frequency(channel, pkt_stat->band);
}
EXPORT_SYMBOL(rtw_set_rx_freq_band);
void rtw_get_channel_params(struct cfg80211_chan_def *chandef, void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
struct rtw_channel_params *chan_params) struct rtw_channel_params *chan_params)
{ {
...@@ -735,6 +748,7 @@ void rtw_set_channel(struct rtw_dev *rtwdev) ...@@ -735,6 +748,7 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
hal->current_band_width = bandwidth; hal->current_band_width = bandwidth;
hal->current_channel = center_chan; hal->current_channel = center_chan;
hal->current_primary_channel_index = primary_chan_idx;
hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
for (i = RTW_CHANNEL_WIDTH_20; i <= RTW_MAX_CHANNEL_WIDTH; i++) for (i = RTW_CHANNEL_WIDTH_20; i <= RTW_MAX_CHANNEL_WIDTH; i++)
...@@ -1278,6 +1292,50 @@ void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start) ...@@ -1278,6 +1292,50 @@ void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
} }
} }
void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
const u8 *mac_addr, bool hw_scan)
{
u32 config = 0;
int ret = 0;
rtw_leave_lps(rtwdev);
if (hw_scan && rtwvif->net_type == RTW_NET_NO_LINK) {
ret = rtw_leave_ips(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to leave idle state\n");
return;
}
}
ether_addr_copy(rtwvif->mac_addr, mac_addr);
config |= PORT_SET_MAC_ADDR;
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);
}
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
{
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = 0;
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);
rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
}
int rtw_core_start(struct rtw_dev *rtwdev) int rtw_core_start(struct rtw_dev *rtwdev)
{ {
int ret; int ret;
...@@ -1952,6 +2010,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ...@@ -1952,6 +2010,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
...@@ -1964,8 +2023,12 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ...@@ -1964,8 +2023,12 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
WIPHY_FLAG_TDLS_EXTERNAL_SETUP; WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS;
hw->wiphy->max_scan_ie_len = RTW_SCAN_MAX_IE_LEN;
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SCAN_RANDOM_SN);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
#ifdef CONFIG_PM #ifdef CONFIG_PM
hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; hw->wiphy->wowlan = rtwdev->chip->wowlan_stub;
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#define RTW_MAX_SEC_CAM_NUM 32 #define RTW_MAX_SEC_CAM_NUM 32
#define MAX_PG_CAM_BACKUP_NUM 8 #define MAX_PG_CAM_BACKUP_NUM 8
#define RTW_SCAN_MAX_SSIDS 4
#define RTW_SCAN_MAX_IE_LEN 128
#define RTW_MAX_PATTERN_NUM 12 #define RTW_MAX_PATTERN_NUM 12
#define RTW_MAX_PATTERN_MASK_SIZE 16 #define RTW_MAX_PATTERN_MASK_SIZE 16
#define RTW_MAX_PATTERN_SIZE 128 #define RTW_MAX_PATTERN_SIZE 128
...@@ -81,11 +84,9 @@ struct rtw_hci { ...@@ -81,11 +84,9 @@ struct rtw_hci {
IS_CH_5G_BAND_3(channel) || IS_CH_5G_BAND_4(channel)) IS_CH_5G_BAND_3(channel) || IS_CH_5G_BAND_4(channel))
enum rtw_supported_band { enum rtw_supported_band {
RTW_BAND_2G = 1 << 0, RTW_BAND_2G = BIT(NL80211_BAND_2GHZ),
RTW_BAND_5G = 1 << 1, RTW_BAND_5G = BIT(NL80211_BAND_5GHZ),
RTW_BAND_60G = 1 << 2, RTW_BAND_60G = BIT(NL80211_BAND_60GHZ),
RTW_BAND_MAX,
}; };
/* now, support upto 80M bw */ /* now, support upto 80M bw */
...@@ -630,6 +631,8 @@ struct rtw_rx_pkt_stat { ...@@ -630,6 +631,8 @@ struct rtw_rx_pkt_stat {
s8 rx_snr[RTW_RF_PATH_MAX]; s8 rx_snr[RTW_RF_PATH_MAX];
u8 rx_evm[RTW_RF_PATH_MAX]; u8 rx_evm[RTW_RF_PATH_MAX];
s8 cfo_tail[RTW_RF_PATH_MAX]; s8 cfo_tail[RTW_RF_PATH_MAX];
u16 freq;
u8 band;
struct rtw_sta_info *si; struct rtw_sta_info *si;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
...@@ -800,6 +803,8 @@ struct rtw_vif { ...@@ -800,6 +803,8 @@ struct rtw_vif {
struct list_head rsvd_page_list; struct list_head rsvd_page_list;
struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS];
const struct rtw_vif_port *conf; const struct rtw_vif_port *conf;
struct cfg80211_scan_request *scan_req;
struct ieee80211_scan_ies *scan_ies;
struct rtw_traffic_stats stats; struct rtw_traffic_stats stats;
...@@ -1819,6 +1824,7 @@ struct rtw_hal { ...@@ -1819,6 +1824,7 @@ struct rtw_hal {
u8 ps_mode; u8 ps_mode;
u8 current_channel; u8 current_channel;
u8 current_primary_channel_index;
u8 current_band_width; u8 current_band_width;
u8 current_band_type; u8 current_band_type;
...@@ -1865,12 +1871,37 @@ struct rtw_path_div { ...@@ -1865,12 +1871,37 @@ struct rtw_path_div {
u16 path_b_cnt; u16 path_b_cnt;
}; };
struct rtw_chan_info {
int pri_ch_idx;
int action_id;
int bw;
u8 extra_info;
u8 channel;
u16 timeout;
};
struct rtw_chan_list {
u32 buf_size;
u32 ch_num;
u32 size;
u16 addr;
};
struct rtw_hw_scan_info {
struct ieee80211_vif *scanning_vif;
u8 probe_pg_size;
u8 op_pri_ch_idx;
u8 op_chan;
u8 op_bw;
};
struct rtw_dev { struct rtw_dev {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
struct rtw_hci hci; struct rtw_hci hci;
struct rtw_hw_scan_info scan_info;
struct rtw_chip_info *chip; struct rtw_chip_info *chip;
struct rtw_hal hal; struct rtw_hal hal;
struct rtw_fifo_conf fifo; struct rtw_fifo_conf fifo;
...@@ -2023,6 +2054,7 @@ static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev) ...@@ -2023,6 +2054,7 @@ static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev)
return 0; return 0;
} }
void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
void rtw_get_channel_params(struct cfg80211_chan_def *chandef, void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
struct rtw_channel_params *ch_param); struct rtw_channel_params *ch_param);
bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target);
...@@ -2037,6 +2069,9 @@ void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ...@@ -2037,6 +2069,9 @@ void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
u32 config); u32 config);
void rtw_tx_report_purge_timer(struct timer_list *t); void rtw_tx_report_purge_timer(struct timer_list *t);
void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
const u8 *mac_addr, bool hw_scan);
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
int rtw_core_start(struct rtw_dev *rtwdev); int rtw_core_start(struct rtw_dev *rtwdev);
void rtw_core_stop(struct rtw_dev *rtwdev); void rtw_core_stop(struct rtw_dev *rtwdev);
int rtw_chip_info_setup(struct rtw_dev *rtwdev); int rtw_chip_info_setup(struct rtw_dev *rtwdev);
......
...@@ -2535,6 +2535,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, ...@@ -2535,6 +2535,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
s8 rx_power[RTW_RF_PATH_MAX]; s8 rx_power[RTW_RF_PATH_MAX];
s8 min_rx_power = -120; s8 min_rx_power = -120;
u8 rssi; u8 rssi;
u8 channel;
int path; int path;
rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status); rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status);
...@@ -2555,6 +2556,11 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, ...@@ -2555,6 +2556,11 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
rx_power[RF_PATH_A] -= 110; rx_power[RF_PATH_A] -= 110;
rx_power[RF_PATH_B] -= 110; rx_power[RF_PATH_B] -= 110;
channel = GET_PHY_STAT_P0_CHANNEL(phy_status);
if (channel == 0)
channel = rtwdev->hal.current_channel;
rtw_set_rx_freq_band(pkt_stat, channel);
pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A]; pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B]; pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
...@@ -2580,6 +2586,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, ...@@ -2580,6 +2586,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
u8 evm_dbm = 0; u8 evm_dbm = 0;
u8 rssi; u8 rssi;
int path; int path;
u8 channel;
if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0) if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status); rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
...@@ -2593,6 +2600,9 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, ...@@ -2593,6 +2600,9 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
else else
bw = RTW_CHANNEL_WIDTH_20; bw = RTW_CHANNEL_WIDTH_20;
channel = GET_PHY_STAT_P1_CHANNEL(phy_status);
rtw_set_rx_freq_band(pkt_stat, channel);
pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110;
pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110; pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110;
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 2); pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 2);
......
...@@ -137,6 +137,8 @@ const struct rtw_table name ## _tbl = { \ ...@@ -137,6 +137,8 @@ const struct rtw_table name ## _tbl = { \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0)) le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P0_GAIN_A(phy_stat) \ #define GET_PHY_STAT_P0_GAIN_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(21, 16)) le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(21, 16))
#define GET_PHY_STAT_P0_CHANNEL(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16))
#define GET_PHY_STAT_P0_GAIN_B(phy_stat) \ #define GET_PHY_STAT_P0_GAIN_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(29, 24)) le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(29, 24))
...@@ -149,6 +151,8 @@ const struct rtw_table name ## _tbl = { \ ...@@ -149,6 +151,8 @@ const struct rtw_table name ## _tbl = { \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8)) le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \ #define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12)) le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_CHANNEL(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \ #define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0)) le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \ #define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "rx.h" #include "rx.h"
#include "ps.h" #include "ps.h"
#include "debug.h" #include "debug.h"
#include "fw.h"
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb) struct sk_buff *skb)
...@@ -138,6 +139,13 @@ static void rtw_rx_addr_match(struct rtw_dev *rtwdev, ...@@ -138,6 +139,13 @@ static void rtw_rx_addr_match(struct rtw_dev *rtwdev,
rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data); rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data);
} }
static void rtw_set_rx_freq_by_pktstat(struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_rx_status *rx_status)
{
rx_status->freq = pkt_stat->freq;
rx_status->band = pkt_stat->band;
}
void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat, struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr, struct ieee80211_hdr *hdr,
...@@ -150,6 +158,8 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, ...@@ -150,6 +158,8 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
memset(rx_status, 0, sizeof(*rx_status)); memset(rx_status, 0, sizeof(*rx_status));
rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band; rx_status->band = hw->conf.chandef.chan->band;
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
if (pkt_stat->crc_err) if (pkt_stat->crc_err)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (pkt_stat->decrypted) if (pkt_stat->decrypted)
......
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