Commit f4a43c3b authored by Dian-Syuan Yang's avatar Dian-Syuan Yang Committed by Kalle Valo
Browse files

wifi: rtw89: support for processing P2P power saving



Support P2P client to process Notice of Absence (NoA) mechanism when it
connects with P2P GO applying an NoA schedule. We define some action
types including init, update, remove and terminate in h2c function to
enable/disable NoA schedule.

Signed-off-by: default avatarDian-Syuan Yang <dian_syuan0116@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/20220922010435.12167-6-pkshih@realtek.com
parent 71392bb2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2205,6 +2205,8 @@ struct rtw89_phy_rate_pattern {
	bool enable;
};

#define RTW89_P2P_MAX_NOA_NUM 2

struct rtw89_vif {
	struct list_head list;
	struct rtw89_dev *rtwdev;
@@ -2220,6 +2222,7 @@ struct rtw89_vif {
	u8 wmm;
	u8 bcn_hit_cond;
	u8 hit_rule;
	u8 last_noa_nr;
	bool trigger;
	bool lsig_txop;
	u8 tgt_ind;
+92 −0
Original line number Diff line number Diff line
@@ -931,6 +931,58 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
	return ret;
}

#define H2C_P2P_ACT_LEN 20
int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
			 struct ieee80211_p2p_noa_desc *desc,
			 u8 act, u8 noa_id)
{
	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
	bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
	u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
	struct sk_buff *skb;
	u8 *cmd;
	int ret;

	skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_P2P_ACT_LEN);
	if (!skb) {
		rtw89_err(rtwdev, "failed to alloc skb for h2c p2p act\n");
		return -ENOMEM;
	}
	skb_put(skb, H2C_P2P_ACT_LEN);
	cmd = skb->data;

	RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif->mac_id);
	RTW89_SET_FWCMD_P2P_P2PID(cmd, 0);
	RTW89_SET_FWCMD_P2P_NOAID(cmd, noa_id);
	RTW89_SET_FWCMD_P2P_ACT(cmd, act);
	RTW89_SET_FWCMD_P2P_TYPE(cmd, p2p_type_gc);
	RTW89_SET_FWCMD_P2P_ALL_SLEP(cmd, 0);
	if (desc) {
		RTW89_SET_FWCMD_NOA_START_TIME(cmd, desc->start_time);
		RTW89_SET_FWCMD_NOA_INTERVAL(cmd, desc->interval);
		RTW89_SET_FWCMD_NOA_DURATION(cmd, desc->duration);
		RTW89_SET_FWCMD_NOA_COUNT(cmd, desc->count);
		RTW89_SET_FWCMD_NOA_CTWINDOW(cmd, ctwindow_oppps);
	}

	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
			      H2C_CAT_MAC, H2C_CL_MAC_PS,
			      H2C_FUNC_P2P_ACT, 0, 0,
			      H2C_P2P_ACT_LEN);

	ret = rtw89_h2c_tx(rtwdev, skb, false);
	if (ret) {
		rtw89_err(rtwdev, "failed to send h2c\n");
		goto fail;
	}

	return 0;
fail:
	dev_kfree_skb_any(skb);

	return ret;
}

static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
				       struct sk_buff *skb)
{
@@ -1447,6 +1499,46 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
	return ret;
}

#define H2C_TSF32_TOGL_LEN 4
int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
			      bool en)
{
	struct sk_buff *skb;
	u16 early_us = en ? 2000 : 0;
	u8 *cmd;
	int ret;

	skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_TSF32_TOGL_LEN);
	if (!skb) {
		rtw89_err(rtwdev, "failed to alloc skb for h2c p2p act\n");
		return -ENOMEM;
	}
	skb_put(skb, H2C_TSF32_TOGL_LEN);
	cmd = skb->data;

	RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif->mac_idx);
	RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, en);
	RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif->port);
	RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, early_us);

	rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
			      H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
			      H2C_FUNC_TSF32_TOGL, 0, 0,
			      H2C_TSF32_TOGL_LEN);

	ret = rtw89_h2c_tx(rtwdev, skb, false);
	if (ret) {
		rtw89_err(rtwdev, "failed to send h2c\n");
		goto fail;
	}

	return 0;
fail:
	dev_kfree_skb_any(skb);

	return ret;
}

#define H2C_OFLD_CFG_LEN 8
int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev)
{
+94 −0
Original line number Diff line number Diff line
@@ -155,6 +155,13 @@ enum rtw89_chan_type {
	RTW89_CHAN_DFS,
};

enum rtw89_p2pps_action {
	RTW89_P2P_ACT_INIT = 0,
	RTW89_P2P_ACT_UPDATE = 1,
	RTW89_P2P_ACT_REMOVE = 2,
	RTW89_P2P_ACT_TERMINATE = 3,
};

#define FWDL_SECTION_MAX_NUM 10
#define FWDL_SECTION_CHKSUM_LEN	8
#define FWDL_SECTION_PER_PKT_LEN 2020
@@ -2442,6 +2449,86 @@ static inline void RTW89_SET_FWCMD_SCANOFLD_TSF_SLOW(void *cmd, u32 val)
	le32p_replace_bits((__le32 *)((u8 *)(cmd) + 16), val, GENMASK(31, 0));
}

static inline void RTW89_SET_FWCMD_P2P_MACID(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(7, 0));
}

static inline void RTW89_SET_FWCMD_P2P_P2PID(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(11, 8));
}

static inline void RTW89_SET_FWCMD_P2P_NOAID(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(15, 12));
}

static inline void RTW89_SET_FWCMD_P2P_ACT(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(19, 16));
}

static inline void RTW89_SET_FWCMD_P2P_TYPE(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, BIT(20));
}

static inline void RTW89_SET_FWCMD_P2P_ALL_SLEP(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, BIT(21));
}

static inline void RTW89_SET_FWCMD_NOA_START_TIME(void *cmd, __le32 val)
{
	*((__le32 *)cmd + 1) = val;
}

static inline void RTW89_SET_FWCMD_NOA_INTERVAL(void *cmd, __le32 val)
{
	*((__le32 *)cmd + 2) = val;
}

static inline void RTW89_SET_FWCMD_NOA_DURATION(void *cmd, __le32 val)
{
	*((__le32 *)cmd + 3) = val;
}

static inline void RTW89_SET_FWCMD_NOA_COUNT(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)(cmd) + 4, val, GENMASK(7, 0));
}

static inline void RTW89_SET_FWCMD_NOA_CTWINDOW(void *cmd, u32 val)
{
	u8 ctwnd;

	if (!(val & IEEE80211_P2P_OPPPS_ENABLE_BIT))
		return;
	ctwnd = FIELD_GET(IEEE80211_P2P_OPPPS_CTWINDOW_MASK, val);
	le32p_replace_bits((__le32 *)(cmd) + 4, ctwnd, GENMASK(23, 8));
}

static inline void RTW89_SET_FWCMD_TSF32_TOGL_BAND(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, BIT(0));
}

static inline void RTW89_SET_FWCMD_TSF32_TOGL_EN(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, BIT(1));
}

static inline void RTW89_SET_FWCMD_TSF32_TOGL_PORT(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(4, 2));
}

static inline void RTW89_SET_FWCMD_TSF32_TOGL_EARLY(void *cmd, u32 val)
{
	le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 16));
}

#define RTW89_C2H_HEADER_LEN 8

#define RTW89_GET_C2H_CATEGORY(c2h) \
@@ -2592,6 +2679,7 @@ struct rtw89_fw_h2c_rf_reg_info {
/* CLASS 2 - PS */
#define H2C_CL_MAC_PS			0x2
#define H2C_FUNC_MAC_LPS_PARM		0x0
#define H2C_FUNC_P2P_ACT		0x1

/* CLASS 3 - FW download */
#define H2C_CL_MAC_FWDL		0x3
@@ -2618,6 +2706,7 @@ struct rtw89_fw_h2c_rf_reg_info {
#define H2C_FUNC_PACKET_OFLD		0x1
#define H2C_FUNC_MAC_MACID_PAUSE	0x8
#define H2C_FUNC_USR_EDCA		0xF
#define H2C_FUNC_TSF32_TOGL		0x10
#define H2C_FUNC_OFLD_CFG		0x14
#define H2C_FUNC_ADD_SCANOFLD_CH	0x16
#define H2C_FUNC_SCANOFLD		0x17
@@ -2751,6 +2840,11 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
			  const struct rtw89_pkt_drop_params *params);
int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
			 struct ieee80211_p2p_noa_desc *desc,
			 u8 act, u8 noa_id);
int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
			      bool en);

static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
{
+7 −0
Original line number Diff line number Diff line
@@ -3843,6 +3843,12 @@ rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
{
}

static void
rtw89_mac_c2h_tsf32_toggle_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
			       u32 len)
{
}

static
void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
					    struct sk_buff *c2h, u32 len) = {
@@ -3852,6 +3858,7 @@ void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
	[RTW89_MAC_C2H_FUNC_BCN_RESEND] = NULL,
	[RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause,
	[RTW89_MAC_C2H_FUNC_SCANOFLD_RSP] = rtw89_mac_c2h_scanofld_rsp,
	[RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT] = rtw89_mac_c2h_tsf32_toggle_rpt,
};

static
+1 −0
Original line number Diff line number Diff line
@@ -306,6 +306,7 @@ enum rtw89_mac_c2h_ofld_func {
	RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP,
	RTW89_MAC_C2H_FUNC_BCN_RESEND,
	RTW89_MAC_C2H_FUNC_MACID_PAUSE,
	RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT = 0x6,
	RTW89_MAC_C2H_FUNC_SCANOFLD_RSP = 0x9,
	RTW89_MAC_C2H_FUNC_OFLD_MAX,
};
Loading