linux/drivers/net/wireless/realtek/rtw88/sec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/* Copyright(c) 2018-2019  Realtek Corporation
   3 */
   4
   5#include "main.h"
   6#include "sec.h"
   7#include "reg.h"
   8
   9int rtw_sec_get_free_cam(struct rtw_sec_desc *sec)
  10{
  11        /* if default key search is enabled, the first 4 cam entries
  12         * are used to direct map to group key with its key->key_idx, so
  13         * driver should use cam entries after 4 to install pairwise key
  14         */
  15        if (sec->default_key_search)
  16                return find_next_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM,
  17                                          RTW_SEC_DEFAULT_KEY_NUM);
  18
  19        return find_first_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM);
  20}
  21
  22void rtw_sec_write_cam(struct rtw_dev *rtwdev,
  23                       struct rtw_sec_desc *sec,
  24                       struct ieee80211_sta *sta,
  25                       struct ieee80211_key_conf *key,
  26                       u8 hw_key_type, u8 hw_key_idx)
  27{
  28        struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx];
  29        u32 write_cmd;
  30        u32 command;
  31        u32 content;
  32        u32 addr;
  33        int i, j;
  34
  35        set_bit(hw_key_idx, sec->cam_map);
  36        cam->valid = true;
  37        cam->group = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
  38        cam->hw_key_type = hw_key_type;
  39        cam->key = key;
  40        if (sta)
  41                ether_addr_copy(cam->addr, sta->addr);
  42        else
  43                eth_broadcast_addr(cam->addr);
  44
  45        write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING;
  46        addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT;
  47        for (i = 5; i >= 0; i--) {
  48                switch (i) {
  49                case 0:
  50                        content = ((key->keyidx & 0x3))         |
  51                                  ((hw_key_type & 0x7)  << 2)   |
  52                                  (cam->group           << 6)   |
  53                                  (cam->valid           << 15)  |
  54                                  (cam->addr[0]         << 16)  |
  55                                  (cam->addr[1]         << 24);
  56                        break;
  57                case 1:
  58                        content = (cam->addr[2])                |
  59                                  (cam->addr[3]         << 8)   |
  60                                  (cam->addr[4]         << 16)  |
  61                                  (cam->addr[5]         << 24);
  62                        break;
  63                default:
  64                        j = (i - 2) << 2;
  65                        content = (key->key[j])                 |
  66                                  (key->key[j + 1]      << 8)   |
  67                                  (key->key[j + 2]      << 16)  |
  68                                  (key->key[j + 3]      << 24);
  69                        break;
  70                }
  71
  72                command = write_cmd | (addr + i);
  73                rtw_write32(rtwdev, RTW_SEC_WRITE_REG, content);
  74                rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
  75        }
  76}
  77
  78void rtw_sec_clear_cam(struct rtw_dev *rtwdev,
  79                       struct rtw_sec_desc *sec,
  80                       u8 hw_key_idx)
  81{
  82        struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx];
  83        u32 write_cmd;
  84        u32 command;
  85        u32 addr;
  86
  87        clear_bit(hw_key_idx, sec->cam_map);
  88        cam->valid = false;
  89        cam->key = NULL;
  90        eth_zero_addr(cam->addr);
  91
  92        write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING;
  93        addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT;
  94        command = write_cmd | addr;
  95        rtw_write32(rtwdev, RTW_SEC_WRITE_REG, 0);
  96        rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
  97}
  98
  99void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev)
 100{
 101        struct rtw_sec_desc *sec = &rtwdev->sec;
 102        u16 ctrl_reg;
 103        u16 sec_config;
 104
 105        /* default use default key search for now */
 106        sec->default_key_search = true;
 107
 108        ctrl_reg = rtw_read16(rtwdev, REG_CR);
 109        ctrl_reg |= RTW_SEC_ENGINE_EN;
 110        rtw_write16(rtwdev, REG_CR, ctrl_reg);
 111
 112        sec_config = rtw_read16(rtwdev, RTW_SEC_CONFIG);
 113
 114        sec_config |= RTW_SEC_TX_DEC_EN | RTW_SEC_RX_DEC_EN;
 115        if (sec->default_key_search)
 116                sec_config |= RTW_SEC_TX_UNI_USE_DK | RTW_SEC_RX_UNI_USE_DK |
 117                              RTW_SEC_TX_BC_USE_DK | RTW_SEC_RX_BC_USE_DK;
 118
 119        rtw_write16(rtwdev, RTW_SEC_CONFIG, sec_config);
 120}
 121