mac80211: rtl8xxxu: sync with linux-next 20240229
[openwrt/staging/981213.git] / package / kernel / mac80211 / patches / rtl / 001-19-v6.9-wifi-rtl8xxxu-add-hw-crypto-support-for-AP-mode.patch
1 From b837f78fbffa5f8e7e7c59879db54793abf161ec Mon Sep 17 00:00:00 2001
2 From: Martin Kaistra <martin.kaistra@linutronix.de>
3 Date: Fri, 22 Dec 2023 11:14:40 +0100
4 Subject: [PATCH 19/21] wifi: rtl8xxxu: add hw crypto support for AP mode
5
6 Add a custom function for allocating entries in the sec cam. This allows
7 us to store multiple keys with the same keyidx.
8
9 The maximum number of sec cam entries for 8188f is 16 according to the
10 vendor driver. Add the number to rtl8xxxu_fileops, so that other chips
11 which might support more entries, can set a different number there.
12
13 Set the bssid as mac address for group keys instead of just using the
14 ethernet broadcast address and use BIT(6) in the sec cam ctrl entry
15 for differentiating them from pairwise keys like in the vendor driver.
16
17 Add the TXDESC_EN_DESC_ID bit and the hw_key_idx to tx
18 broadcast/multicast packets in AP mode.
19
20 Finally, allow the usage of rtl8xxxu_set_key() for AP mode.
21
22 Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
23 Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
24 Signed-off-by: Kalle Valo <kvalo@kernel.org>
25 Link: https://msgid.link/20231222101442.626837-20-martin.kaistra@linutronix.de
26 ---
27 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ++
28 .../realtek/rtl8xxxu/rtl8xxxu_8188f.c | 1 +
29 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 48 +++++++++++++++----
30 3 files changed, 44 insertions(+), 10 deletions(-)
31
32 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
33 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
34 @@ -498,6 +498,7 @@ struct rtl8xxxu_txdesc40 {
35 #define DESC_RATE_ID_SHIFT 16
36 #define DESC_RATE_ID_MASK 0xf
37 #define TXDESC_NAVUSEHDR BIT(20)
38 +#define TXDESC_EN_DESC_ID BIT(21)
39 #define TXDESC_SEC_RC4 0x00400000
40 #define TXDESC_SEC_AES 0x00c00000
41 #define TXDESC_PKT_OFFSET_SHIFT 26
42 @@ -1775,6 +1776,7 @@ struct rtl8xxxu_cfo_tracking {
43 #define RTL8XXXU_MAX_MAC_ID_NUM 128
44 #define RTL8XXXU_BC_MC_MACID 0
45 #define RTL8XXXU_BC_MC_MACID1 1
46 +#define RTL8XXXU_MAX_SEC_CAM_NUM 64
47
48 struct rtl8xxxu_priv {
49 struct ieee80211_hw *hw;
50 @@ -1908,6 +1910,7 @@ struct rtl8xxxu_priv {
51 char led_name[32];
52 struct led_classdev led_cdev;
53 DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
54 + DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM);
55 };
56
57 struct rtl8xxxu_sta_info {
58 @@ -1919,6 +1922,7 @@ struct rtl8xxxu_sta_info {
59
60 struct rtl8xxxu_vif {
61 int port_num;
62 + u8 hw_key_idx;
63 };
64
65 struct rtl8xxxu_rx_urb {
66 @@ -1993,6 +1997,7 @@ struct rtl8xxxu_fileops {
67 u16 max_aggr_num;
68 u8 supports_ap:1;
69 u16 max_macid_num;
70 + u16 max_sec_cam_num;
71 u32 adda_1t_init;
72 u32 adda_1t_path_on;
73 u32 adda_2t_path_on_a;
74 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
75 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
76 @@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops =
77 .max_aggr_num = 0x0c14,
78 .supports_ap = 1,
79 .max_macid_num = 16,
80 + .max_sec_cam_num = 16,
81 .adda_1t_init = 0x03c00014,
82 .adda_1t_path_on = 0x03c00014,
83 .trxff_boundary = 0x3f7f,
84 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
85 +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
86 @@ -4559,8 +4559,10 @@ static void rtl8xxxu_cam_write(struct rt
87 * This is a bit of a hack - the lower bits of the cipher
88 * suite selector happens to match the cipher index in the CAM
89 */
90 - addr = key->keyidx << CAM_CMD_KEY_SHIFT;
91 + addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT;
92 ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID;
93 + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
94 + ctrl |= BIT(6);
95
96 for (j = 5; j >= 0; j--) {
97 switch (j) {
98 @@ -5546,13 +5548,14 @@ static void rtl8xxxu_tx(struct ieee80211
99 struct rtl8xxxu_tx_urb *tx_urb;
100 struct ieee80211_sta *sta = NULL;
101 struct ieee80211_vif *vif = tx_info->control.vif;
102 + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
103 struct device *dev = &priv->udev->dev;
104 u32 queue, rts_rate;
105 u16 pktlen = skb->len;
106 int tx_desc_size = priv->fops->tx_desc_size;
107 u8 macid;
108 int ret;
109 - bool ampdu_enable, sgi = false, short_preamble = false;
110 + bool ampdu_enable, sgi = false, short_preamble = false, bmc = false;
111
112 if (skb_headroom(skb) < tx_desc_size) {
113 dev_warn(dev,
114 @@ -5594,10 +5597,14 @@ static void rtl8xxxu_tx(struct ieee80211
115 tx_desc->txdw0 =
116 TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
117 if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
118 - is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
119 + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
120 tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
121 + bmc = true;
122 + }
123 +
124
125 tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
126 + macid = rtl8xxxu_get_macid(priv, sta);
127
128 if (tx_info->control.hw_key) {
129 switch (tx_info->control.hw_key->cipher) {
130 @@ -5612,6 +5619,10 @@ static void rtl8xxxu_tx(struct ieee80211
131 default:
132 break;
133 }
134 + if (bmc && rtlvif->hw_key_idx != 0xff) {
135 + tx_desc->txdw1 |= TXDESC_EN_DESC_ID;
136 + macid = rtlvif->hw_key_idx;
137 + }
138 }
139
140 /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */
141 @@ -5655,7 +5666,6 @@ static void rtl8xxxu_tx(struct ieee80211
142 else
143 rts_rate = 0;
144
145 - macid = rtl8xxxu_get_macid(priv, sta);
146 priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
147 ampdu_enable, rts_rate, macid);
148
149 @@ -6667,6 +6677,7 @@ static int rtl8xxxu_add_interface(struct
150
151 priv->vifs[port_num] = vif;
152 rtlvif->port_num = port_num;
153 + rtlvif->hw_key_idx = 0xff;
154
155 rtl8xxxu_set_linktype(priv, vif->type, port_num);
156 ether_addr_copy(priv->mac_addr, vif->addr);
157 @@ -6843,11 +6854,19 @@ static int rtl8xxxu_set_rts_threshold(st
158 return 0;
159 }
160
161 +static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw)
162 +{
163 + struct rtl8xxxu_priv *priv = hw->priv;
164 +
165 + return find_first_zero_bit(priv->cam_map, priv->fops->max_sec_cam_num);
166 +}
167 +
168 static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
169 struct ieee80211_vif *vif,
170 struct ieee80211_sta *sta,
171 struct ieee80211_key_conf *key)
172 {
173 + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
174 struct rtl8xxxu_priv *priv = hw->priv;
175 struct device *dev = &priv->udev->dev;
176 u8 mac_addr[ETH_ALEN];
177 @@ -6859,9 +6878,6 @@ static int rtl8xxxu_set_key(struct ieee8
178 dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n",
179 __func__, cmd, key->cipher, key->keyidx);
180
181 - if (vif->type != NL80211_IFTYPE_STATION)
182 - return -EOPNOTSUPP;
183 -
184 if (key->keyidx > 3)
185 return -EOPNOTSUPP;
186
187 @@ -6885,7 +6901,7 @@ static int rtl8xxxu_set_key(struct ieee8
188 ether_addr_copy(mac_addr, sta->addr);
189 } else {
190 dev_dbg(dev, "%s: group key\n", __func__);
191 - eth_broadcast_addr(mac_addr);
192 + ether_addr_copy(mac_addr, vif->bss_conf.bssid);
193 }
194
195 val16 = rtl8xxxu_read16(priv, REG_CR);
196 @@ -6899,16 +6915,28 @@ static int rtl8xxxu_set_key(struct ieee8
197
198 switch (cmd) {
199 case SET_KEY:
200 - key->hw_key_idx = key->keyidx;
201 +
202 + retval = rtl8xxxu_get_free_sec_cam(hw);
203 + if (retval < 0)
204 + return -EOPNOTSUPP;
205 +
206 + key->hw_key_idx = retval;
207 +
208 + if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
209 + rtlvif->hw_key_idx = key->hw_key_idx;
210 +
211 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
212 rtl8xxxu_cam_write(priv, key, mac_addr);
213 + set_bit(key->hw_key_idx, priv->cam_map);
214 retval = 0;
215 break;
216 case DISABLE_KEY:
217 rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000);
218 val32 = CAM_CMD_POLLING | CAM_CMD_WRITE |
219 - key->keyidx << CAM_CMD_KEY_SHIFT;
220 + key->hw_key_idx << CAM_CMD_KEY_SHIFT;
221 rtl8xxxu_write32(priv, REG_CAM_CMD, val32);
222 + rtlvif->hw_key_idx = 0xff;
223 + clear_bit(key->hw_key_idx, priv->cam_map);
224 retval = 0;
225 break;
226 default: