Commit 19e28c7f authored by Chin-Yen Lee's avatar Chin-Yen Lee Committed by Kalle Valo
Browse files

wifi: rtw89: add WoWLAN function support



WoWLAN is a feature which allows devices to be woken up from suspend
state through WLAN events.

When user enables WoWLAN feature and then let the device enter suspend
state, WoWLAN firmware will be loaded by the driver and periodically
monitors WiFi packets. Power consumption of WiFi chip will be reduced
in this state.

We now implement WoWLAN function in rtw8852ae and rtw8852ce chip.
Currently supported WLAN events include receiving magic packet,
rekey packet and deauth packet, and disconnecting from AP.

Signed-off-by: default avatarChin-Yen Lee <timlee@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/20221027052707.14605-7-pkshih@realtek.com
parent ee88d748
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@ rtw89_core-y += core.o \
		chan.o \
		ser.o

rtw89_core-$(CONFIG_PM) += wow.o

obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
rtw89_8852a-objs := rtw8852a.o \
		    rtw8852a_table.o \
+8 −0
Original line number Diff line number Diff line
@@ -2204,6 +2204,9 @@ static void rtw89_track_work(struct work_struct *work)
						track_work.work);
	bool tfc_changed;

	if (test_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags))
		return;

	mutex_lock(&rtwdev->mutex);

	if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
@@ -3042,6 +3045,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
			continue;
		INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]);
	}
	INIT_LIST_HEAD(&rtwdev->wow.pkt_list);
	INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work);
	INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work);
	INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work);
@@ -3273,6 +3277,10 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
	hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID;
	hw->wiphy->max_scan_ie_len = RTW89_SCANOFLD_MAX_IE_LEN;

#ifdef CONFIG_PM
	hw->wiphy->wowlan = rtwdev->chip->wowlan_stub;
#endif

	hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
	hw->wiphy->tid_config_support.peer |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
	hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
+76 −1
Original line number Diff line number Diff line
@@ -178,7 +178,9 @@ enum rtw89_upd_mode {
	RTW89_ROLE_REMOVE,
	RTW89_ROLE_TYPE_CHANGE,
	RTW89_ROLE_INFO_CHANGE,
	RTW89_ROLE_CON_DISCONN
	RTW89_ROLE_CON_DISCONN,
	RTW89_ROLE_BAND_SW,
	RTW89_ROLE_FW_RESTORE,
};

enum rtw89_self_role {
@@ -2307,6 +2309,16 @@ struct rtw89_hci_ops {
	 */
	void (*recovery_start)(struct rtw89_dev *rtwdev);
	void (*recovery_complete)(struct rtw89_dev *rtwdev);

	void (*ctrl_txdma_ch)(struct rtw89_dev *rtwdev, bool enable);
	void (*ctrl_txdma_fw_ch)(struct rtw89_dev *rtwdev, bool enable);
	void (*ctrl_trxhci)(struct rtw89_dev *rtwdev, bool enable);
	int (*poll_txdma_ch)(struct rtw89_dev *rtwdev);
	void (*clr_idx_all)(struct rtw89_dev *rtwdev);
	void (*clear)(struct rtw89_dev *rtwdev, struct pci_dev *pdev);
	void (*disable_intr)(struct rtw89_dev *rtwdev);
	void (*enable_intr)(struct rtw89_dev *rtwdev);
	int (*rst_bdram)(struct rtw89_dev *rtwdev);
};

struct rtw89_hci_info {
@@ -2748,6 +2760,7 @@ struct rtw89_chip_info {
	const struct rtw89_imr_info *imr_info;
	const struct rtw89_rrsr_cfgs *rrsr_cfgs;
	u32 dma_ch_mask;
	const struct wiphy_wowlan_support *wowlan_stub;
};

union rtw89_bus_info {
@@ -2944,6 +2957,8 @@ enum rtw89_flags {
	RTW89_FLAG_LOW_POWER_MODE,
	RTW89_FLAG_INACTIVE_PS,
	RTW89_FLAG_CRASH_SIMULATING,
	RTW89_FLAG_WOWLAN,
	RTW89_FLAG_FORBIDDEN_TRACK_WROK,

	NUM_OF_RTW89_FLAGS,
};
@@ -3653,6 +3668,66 @@ static inline void rtw89_hci_recovery_complete(struct rtw89_dev *rtwdev)
		rtwdev->hci.ops->recovery_complete(rtwdev);
}

static inline void rtw89_hci_enable_intr(struct rtw89_dev *rtwdev)
{
	if (rtwdev->hci.ops->enable_intr)
		rtwdev->hci.ops->enable_intr(rtwdev);
}

static inline void rtw89_hci_disable_intr(struct rtw89_dev *rtwdev)
{
	if (rtwdev->hci.ops->disable_intr)
		rtwdev->hci.ops->disable_intr(rtwdev);
}

static inline void rtw89_hci_ctrl_txdma_ch(struct rtw89_dev *rtwdev, bool enable)
{
	if (rtwdev->hci.ops->ctrl_txdma_ch)
		rtwdev->hci.ops->ctrl_txdma_ch(rtwdev, enable);
}

static inline void rtw89_hci_ctrl_txdma_fw_ch(struct rtw89_dev *rtwdev, bool enable)
{
	if (rtwdev->hci.ops->ctrl_txdma_fw_ch)
		rtwdev->hci.ops->ctrl_txdma_fw_ch(rtwdev, enable);
}

static inline void rtw89_hci_ctrl_trxhci(struct rtw89_dev *rtwdev, bool enable)
{
	if (rtwdev->hci.ops->ctrl_trxhci)
		rtwdev->hci.ops->ctrl_trxhci(rtwdev, enable);
}

static inline int rtw89_hci_poll_txdma_ch(struct rtw89_dev *rtwdev)
{
	int ret = 0;

	if (rtwdev->hci.ops->poll_txdma_ch)
		ret = rtwdev->hci.ops->poll_txdma_ch(rtwdev);
	return ret;
}

static inline void rtw89_hci_clr_idx_all(struct rtw89_dev *rtwdev)
{
	if (rtwdev->hci.ops->clr_idx_all)
		rtwdev->hci.ops->clr_idx_all(rtwdev);
}

static inline int rtw89_hci_rst_bdram(struct rtw89_dev *rtwdev)
{
	int ret = 0;

	if (rtwdev->hci.ops->rst_bdram)
		ret = rtwdev->hci.ops->rst_bdram(rtwdev);
	return ret;
}

static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pdev)
{
	if (rtwdev->hci.ops->clear)
		rtwdev->hci.ops->clear(rtwdev, pdev);
}

static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr)
{
	return rtwdev->hci.ops->read8(rtwdev, addr);
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ enum rtw89_debug_mask {
	RTW89_DBG_HW_SCAN = BIT(15),
	RTW89_DBG_SAR = BIT(16),
	RTW89_DBG_STATE = BIT(17),
	RTW89_DBG_WOW = BIT(18),

	RTW89_DBG_UNEXP = BIT(31),
};
+14 −4
Original line number Diff line number Diff line
@@ -1566,6 +1566,16 @@ int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow)
}
#undef SET_QUOTA

void rtw89_mac_hw_mgnt_sec(struct rtw89_dev *rtwdev, bool enable)
{
	u32 msk32 = B_AX_UC_MGNT_DEC | B_AX_BMC_MGNT_DEC;

	if (enable)
		rtw89_write32_set(rtwdev, R_AX_SEC_ENG_CTRL, msk32);
	else
		rtw89_write32_clr(rtwdev, R_AX_SEC_ENG_CTRL, msk32);
}

static void dle_quota_cfg(struct rtw89_dev *rtwdev,
			  const struct rtw89_dle_mem *cfg,
			  u16 ext_wde_min_qt_wcpu)
@@ -1915,7 +1925,7 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
	return 0;
}

static int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev,
int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev,
			   enum rtw89_machdr_frame_type type,
			   enum rtw89_mac_fwd_target fwd_target,
			   u8 mac_idx)
Loading