Commit 79a6c9a4 authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo
Browse files

rtw89: support hardware generate security header



The newer chip will generate security header itself, so don't set
IEEE80211_KEY_FLAG_GENERATE_IV in this kind of chip. But, it needs to fill
key_index, PN and 802.11 header length to TX descriptor, and then hardware
uses these to generate security header.

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/20220318023214.32411-11-pkshih@realtek.com
parent f59acdde
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -320,6 +320,7 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
			  struct ieee80211_sta *sta,
			  struct ieee80211_key_conf *key)
{
	const struct rtw89_chip_info *chip = rtwdev->chip;
	u8 hw_key_type;
	bool ext_key = false;
	int ret;
@@ -353,6 +354,7 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
		return -EOPNOTSUPP;
	}

	if (!chip->hw_sec_hdr)
		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;

	ret = rtw89_cam_sec_key_install(rtwdev, vif, sta, key, hw_key_type,
+50 −0
Original line number Diff line number Diff line
@@ -435,6 +435,7 @@ static void
rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
			     struct rtw89_core_tx_request *tx_req)
{
	const struct rtw89_chip_info *chip = rtwdev->chip;
	struct ieee80211_vif *vif = tx_req->vif;
	struct ieee80211_sta *sta = tx_req->sta;
	struct ieee80211_tx_info *info;
@@ -446,6 +447,7 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
	struct sk_buff *skb = tx_req->skb;
	u8 sec_type = RTW89_SEC_KEY_TYPE_NONE;
	u64 pn64;

	if (!vif) {
		rtw89_warn(rtwdev, "cannot set sec key without vif\n");
@@ -491,8 +493,21 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
	}

	desc_info->sec_en = true;
	desc_info->sec_keyid = key->keyidx;
	desc_info->sec_type = sec_type;
	desc_info->sec_cam_idx = sec_cam->sec_cam_idx;

	if (!chip->hw_sec_hdr)
		return;

	pn64 = atomic64_inc_return(&key->tx_pn);
	desc_info->sec_seq[0] = pn64;
	desc_info->sec_seq[1] = pn64 >> 8;
	desc_info->sec_seq[2] = pn64 >> 16;
	desc_info->sec_seq[3] = pn64 >> 24;
	desc_info->sec_seq[4] = pn64 >> 32;
	desc_info->sec_seq[5] = pn64 >> 40;
	desc_info->wp_offset = 1; /* in unit of 8 bytes for security header */
}

static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
@@ -755,6 +770,17 @@ rtw89_core_tx_btc_spec_pkt_notify(struct rtw89_dev *rtwdev,
	return PACKET_MAX;
}

static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev,
					 struct rtw89_tx_desc_info *desc_info,
					 struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (void *)skb->data;
	__le16 fc = hdr->frame_control;

	desc_info->hdr_llc_len = ieee80211_hdrlen(fc);
	desc_info->hdr_llc_len >>= 1; /* in unit of 2 bytes */
}

static void
rtw89_core_tx_wake(struct rtw89_dev *rtwdev,
		   struct rtw89_core_tx_request *tx_req)
@@ -806,6 +832,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
		rtw89_core_tx_update_data_info(rtwdev, tx_req);
		pkt_type = rtw89_core_tx_btc_spec_pkt_notify(rtwdev, tx_req);
		rtw89_core_tx_update_he_qos_htc(rtwdev, tx_req, pkt_type);
		rtw89_core_tx_update_llc_hdr(rtwdev, desc_info, skb);
		break;
	case RTW89_CORE_TX_TYPE_FWCMD:
		rtw89_core_tx_update_h2c_info(rtwdev, tx_req);
@@ -912,6 +939,7 @@ static __le32 rtw89_build_txwd_body0_v1(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_body1_v1(struct rtw89_tx_desc_info *desc_info)
{
	u32 dword = FIELD_PREP(RTW89_TXWD_BODY1_ADDR_INFO_NUM, desc_info->addr_info_nr) |
		    FIELD_PREP(RTW89_TXWD_BODY1_SEC_KEYID, desc_info->sec_keyid) |
		    FIELD_PREP(RTW89_TXWD_BODY1_SEC_TYPE, desc_info->sec_type);

	return cpu_to_le32(dword);
@@ -936,6 +964,24 @@ static __le32 rtw89_build_txwd_body3(struct rtw89_tx_desc_info *desc_info)
	return cpu_to_le32(dword);
}

static __le32 rtw89_build_txwd_body4(struct rtw89_tx_desc_info *desc_info)
{
	u32 dword = FIELD_PREP(RTW89_TXWD_BODY4_SEC_IV_L0, desc_info->sec_seq[0]) |
		    FIELD_PREP(RTW89_TXWD_BODY4_SEC_IV_L1, desc_info->sec_seq[1]);

	return cpu_to_le32(dword);
}

static __le32 rtw89_build_txwd_body5(struct rtw89_tx_desc_info *desc_info)
{
	u32 dword = FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H2, desc_info->sec_seq[2]) |
		    FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H3, desc_info->sec_seq[3]) |
		    FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H4, desc_info->sec_seq[4]) |
		    FIELD_PREP(RTW89_TXWD_BODY5_SEC_IV_H5, desc_info->sec_seq[5]);

	return cpu_to_le32(dword);
}

static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info)
{
	u32 dword = FIELD_PREP(RTW89_TXWD_BODY7_USE_RATE_V1, desc_info->use_rate) |
@@ -1032,6 +1078,10 @@ void rtw89_core_fill_txdesc_v1(struct rtw89_dev *rtwdev,
	txwd_body->dword1 = rtw89_build_txwd_body1_v1(desc_info);
	txwd_body->dword2 = rtw89_build_txwd_body2(desc_info);
	txwd_body->dword3 = rtw89_build_txwd_body3(desc_info);
	if (desc_info->sec_en) {
		txwd_body->dword4 = rtw89_build_txwd_body4(desc_info);
		txwd_body->dword5 = rtw89_build_txwd_body5(desc_info);
	}
	txwd_body->dword7 = rtw89_build_txwd_body7_v1(desc_info);

	if (!desc_info->en_wd_info)
+3 −0
Original line number Diff line number Diff line
@@ -733,8 +733,10 @@ struct rtw89_tx_desc_info {
	u8 ampdu_num;
	bool sec_en;
	u8 addr_info_nr;
	u8 sec_keyid;
	u8 sec_type;
	u8 sec_cam_idx;
	u8 sec_seq[6];
	u16 data_rate;
	u16 data_retry_lowest_rate;
	bool fw_dl;
@@ -2302,6 +2304,7 @@ struct rtw89_chip_info {
	u32 rf_base_addr[2];
	u8 support_bands;
	bool support_bw160;
	bool hw_sec_hdr;
	u8 rf_path_num;
	u8 tx_nss;
	u8 rx_nss;
+1 −0
Original line number Diff line number Diff line
@@ -2066,6 +2066,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
	.support_bands		= BIT(NL80211_BAND_2GHZ) |
				  BIT(NL80211_BAND_5GHZ),
	.support_bw160		= false,
	.hw_sec_hdr		= false,
	.rf_path_num		= 2,
	.tx_nss			= 2,
	.rx_nss			= 2,
+1 −0
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
	.rf_base_addr		= {0xe000, 0xf000},
	.pwr_on_seq		= NULL,
	.pwr_off_seq		= NULL,
	.hw_sec_hdr		= true,
	.sec_ctrl_efuse_size	= 4,
	.physical_efuse_size	= 1216,
	.logical_efuse_size	= 2048,
Loading