mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-13 09:15:02 +08:00
504e2b2882
8723D adds some experimental features to word 0x06 of cam entry, so fill zeros to initialize them to off state. For existing chips, these two words are reserved and always zeros, so this change is harmless for them. Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20200512102621.5148-9-yhchuang@realtek.com
146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
// 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);
|
|
}
|