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