123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- From b837f78fbffa5f8e7e7c59879db54793abf161ec Mon Sep 17 00:00:00 2001
- From: Martin Kaistra <[email protected]>
- Date: Fri, 22 Dec 2023 11:14:40 +0100
- Subject: [PATCH 19/21] wifi: rtl8xxxu: add hw crypto support for AP mode
- Add a custom function for allocating entries in the sec cam. This allows
- us to store multiple keys with the same keyidx.
- The maximum number of sec cam entries for 8188f is 16 according to the
- vendor driver. Add the number to rtl8xxxu_fileops, so that other chips
- which might support more entries, can set a different number there.
- Set the bssid as mac address for group keys instead of just using the
- ethernet broadcast address and use BIT(6) in the sec cam ctrl entry
- for differentiating them from pairwise keys like in the vendor driver.
- Add the TXDESC_EN_DESC_ID bit and the hw_key_idx to tx
- broadcast/multicast packets in AP mode.
- Finally, allow the usage of rtl8xxxu_set_key() for AP mode.
- Signed-off-by: Martin Kaistra <[email protected]>
- Reviewed-by: Ping-Ke Shih <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- Link: https://msgid.link/[email protected]
- ---
- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 5 ++
- .../realtek/rtl8xxxu/rtl8xxxu_8188f.c | 1 +
- .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 48 +++++++++++++++----
- 3 files changed, 44 insertions(+), 10 deletions(-)
- --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
- +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
- @@ -498,6 +498,7 @@ struct rtl8xxxu_txdesc40 {
- #define DESC_RATE_ID_SHIFT 16
- #define DESC_RATE_ID_MASK 0xf
- #define TXDESC_NAVUSEHDR BIT(20)
- +#define TXDESC_EN_DESC_ID BIT(21)
- #define TXDESC_SEC_RC4 0x00400000
- #define TXDESC_SEC_AES 0x00c00000
- #define TXDESC_PKT_OFFSET_SHIFT 26
- @@ -1775,6 +1776,7 @@ struct rtl8xxxu_cfo_tracking {
- #define RTL8XXXU_MAX_MAC_ID_NUM 128
- #define RTL8XXXU_BC_MC_MACID 0
- #define RTL8XXXU_BC_MC_MACID1 1
- +#define RTL8XXXU_MAX_SEC_CAM_NUM 64
-
- struct rtl8xxxu_priv {
- struct ieee80211_hw *hw;
- @@ -1908,6 +1910,7 @@ struct rtl8xxxu_priv {
- char led_name[32];
- struct led_classdev led_cdev;
- DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
- + DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM);
- };
-
- struct rtl8xxxu_sta_info {
- @@ -1919,6 +1922,7 @@ struct rtl8xxxu_sta_info {
-
- struct rtl8xxxu_vif {
- int port_num;
- + u8 hw_key_idx;
- };
-
- struct rtl8xxxu_rx_urb {
- @@ -1993,6 +1997,7 @@ struct rtl8xxxu_fileops {
- u16 max_aggr_num;
- u8 supports_ap:1;
- u16 max_macid_num;
- + u16 max_sec_cam_num;
- u32 adda_1t_init;
- u32 adda_1t_path_on;
- u32 adda_2t_path_on_a;
- --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
- +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
- @@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops =
- .max_aggr_num = 0x0c14,
- .supports_ap = 1,
- .max_macid_num = 16,
- + .max_sec_cam_num = 16,
- .adda_1t_init = 0x03c00014,
- .adda_1t_path_on = 0x03c00014,
- .trxff_boundary = 0x3f7f,
- --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
- +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
- @@ -4559,8 +4559,10 @@ static void rtl8xxxu_cam_write(struct rt
- * This is a bit of a hack - the lower bits of the cipher
- * suite selector happens to match the cipher index in the CAM
- */
- - addr = key->keyidx << CAM_CMD_KEY_SHIFT;
- + addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT;
- ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID;
- + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
- + ctrl |= BIT(6);
-
- for (j = 5; j >= 0; j--) {
- switch (j) {
- @@ -5546,13 +5548,14 @@ static void rtl8xxxu_tx(struct ieee80211
- struct rtl8xxxu_tx_urb *tx_urb;
- struct ieee80211_sta *sta = NULL;
- struct ieee80211_vif *vif = tx_info->control.vif;
- + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
- struct device *dev = &priv->udev->dev;
- u32 queue, rts_rate;
- u16 pktlen = skb->len;
- int tx_desc_size = priv->fops->tx_desc_size;
- u8 macid;
- int ret;
- - bool ampdu_enable, sgi = false, short_preamble = false;
- + bool ampdu_enable, sgi = false, short_preamble = false, bmc = false;
-
- if (skb_headroom(skb) < tx_desc_size) {
- dev_warn(dev,
- @@ -5594,10 +5597,14 @@ static void rtl8xxxu_tx(struct ieee80211
- tx_desc->txdw0 =
- TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
- if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
- - is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
- + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
- tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
- + bmc = true;
- + }
- +
-
- tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
- + macid = rtl8xxxu_get_macid(priv, sta);
-
- if (tx_info->control.hw_key) {
- switch (tx_info->control.hw_key->cipher) {
- @@ -5612,6 +5619,10 @@ static void rtl8xxxu_tx(struct ieee80211
- default:
- break;
- }
- + if (bmc && rtlvif->hw_key_idx != 0xff) {
- + tx_desc->txdw1 |= TXDESC_EN_DESC_ID;
- + macid = rtlvif->hw_key_idx;
- + }
- }
-
- /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */
- @@ -5655,7 +5666,6 @@ static void rtl8xxxu_tx(struct ieee80211
- else
- rts_rate = 0;
-
- - macid = rtl8xxxu_get_macid(priv, sta);
- priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
- ampdu_enable, rts_rate, macid);
-
- @@ -6667,6 +6677,7 @@ static int rtl8xxxu_add_interface(struct
-
- priv->vifs[port_num] = vif;
- rtlvif->port_num = port_num;
- + rtlvif->hw_key_idx = 0xff;
-
- rtl8xxxu_set_linktype(priv, vif->type, port_num);
- ether_addr_copy(priv->mac_addr, vif->addr);
- @@ -6843,11 +6854,19 @@ static int rtl8xxxu_set_rts_threshold(st
- return 0;
- }
-
- +static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw)
- +{
- + struct rtl8xxxu_priv *priv = hw->priv;
- +
- + return find_first_zero_bit(priv->cam_map, priv->fops->max_sec_cam_num);
- +}
- +
- static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
- {
- + struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
- struct rtl8xxxu_priv *priv = hw->priv;
- struct device *dev = &priv->udev->dev;
- u8 mac_addr[ETH_ALEN];
- @@ -6859,9 +6878,6 @@ static int rtl8xxxu_set_key(struct ieee8
- dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n",
- __func__, cmd, key->cipher, key->keyidx);
-
- - if (vif->type != NL80211_IFTYPE_STATION)
- - return -EOPNOTSUPP;
- -
- if (key->keyidx > 3)
- return -EOPNOTSUPP;
-
- @@ -6885,7 +6901,7 @@ static int rtl8xxxu_set_key(struct ieee8
- ether_addr_copy(mac_addr, sta->addr);
- } else {
- dev_dbg(dev, "%s: group key\n", __func__);
- - eth_broadcast_addr(mac_addr);
- + ether_addr_copy(mac_addr, vif->bss_conf.bssid);
- }
-
- val16 = rtl8xxxu_read16(priv, REG_CR);
- @@ -6899,16 +6915,28 @@ static int rtl8xxxu_set_key(struct ieee8
-
- switch (cmd) {
- case SET_KEY:
- - key->hw_key_idx = key->keyidx;
- +
- + retval = rtl8xxxu_get_free_sec_cam(hw);
- + if (retval < 0)
- + return -EOPNOTSUPP;
- +
- + key->hw_key_idx = retval;
- +
- + if (vif->type == NL80211_IFTYPE_AP && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
- + rtlvif->hw_key_idx = key->hw_key_idx;
- +
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- rtl8xxxu_cam_write(priv, key, mac_addr);
- + set_bit(key->hw_key_idx, priv->cam_map);
- retval = 0;
- break;
- case DISABLE_KEY:
- rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000);
- val32 = CAM_CMD_POLLING | CAM_CMD_WRITE |
- - key->keyidx << CAM_CMD_KEY_SHIFT;
- + key->hw_key_idx << CAM_CMD_KEY_SHIFT;
- rtl8xxxu_write32(priv, REG_CAM_CMD, val32);
- + rtlvif->hw_key_idx = 0xff;
- + clear_bit(key->hw_key_idx, priv->cam_map);
- retval = 0;
- break;
- default:
|