1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. 4 * 5 * Based on the r8180 driver, which is: 6 * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. 7 * 8 * Contact Information: wlanfae <wlanfae@realtek.com> 9 */ 10 #include "rtl_core.h" 11 #include "r8192E_phy.h" 12 #include "r8192E_phyreg.h" 13 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */ 14 #include "r8192E_cmdpkt.h" 15 16 void rtl92e_cam_reset(struct net_device *dev) 17 { 18 u32 ulcommand = 0; 19 20 ulcommand |= BIT31 | BIT30; 21 rtl92e_writel(dev, RWCAM, ulcommand); 22 } 23 24 void rtl92e_enable_hw_security_config(struct net_device *dev) 25 { 26 u8 SECR_value = 0x0; 27 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); 28 struct rtllib_device *ieee = priv->rtllib; 29 30 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable; 31 if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) || 32 (ieee->pairwise_key_type == KEY_TYPE_WEP104)) && 33 (priv->rtllib->auth_mode != 2)) { 34 SECR_value |= SCR_RxUseDK; 35 SECR_value |= SCR_TxUseDK; 36 } else if ((ieee->iw_mode == IW_MODE_ADHOC) && 37 (ieee->pairwise_key_type & (KEY_TYPE_CCMP | 38 KEY_TYPE_TKIP))) { 39 SECR_value |= SCR_RxUseDK; 40 SECR_value |= SCR_TxUseDK; 41 } 42 43 ieee->hwsec_active = 1; 44 if ((ieee->ht_info->iot_action & HT_IOT_ACT_PURE_N_MODE) || !hwwep) { 45 ieee->hwsec_active = 0; 46 SECR_value &= ~SCR_RxDecEnable; 47 } 48 rtl92e_writeb(dev, SECR, SECR_value); 49 } 50 51 void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, 52 u16 KeyType, const u8 *MacAddr, u32 *KeyContent) 53 { 54 struct r8192_priv *priv = rtllib_priv(dev); 55 struct rtllib_device *ieee = priv->rtllib; 56 57 if (EntryNo >= TOTAL_CAM_ENTRY) 58 return; 59 60 ieee->swcamtable[EntryNo].bused = true; 61 ieee->swcamtable[EntryNo].key_index = KeyIndex; 62 ieee->swcamtable[EntryNo].key_type = KeyType; 63 memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6); 64 ieee->swcamtable[EntryNo].useDK = 0; 65 memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16); 66 } 67 68 void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, 69 u16 KeyType, const u8 *MacAddr, u8 DefaultKey, 70 u32 *KeyContent) 71 { 72 u32 TargetCommand = 0; 73 u32 TargetContent = 0; 74 u16 usConfig = 0; 75 u8 i; 76 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); 77 enum rt_rf_power_state rt_state; 78 79 rt_state = priv->rtllib->rf_power_state; 80 if (rt_state == rf_off) { 81 if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) { 82 netdev_warn(dev, "%s(): RF is OFF.\n", 83 __func__); 84 return; 85 } 86 mutex_lock(&priv->rtllib->ips_mutex); 87 rtl92e_ips_leave(dev); 88 mutex_unlock(&priv->rtllib->ips_mutex); 89 } 90 priv->rtllib->is_set_key = true; 91 if (EntryNo >= TOTAL_CAM_ENTRY) { 92 netdev_info(dev, "%s(): Invalid CAM entry\n", __func__); 93 return; 94 } 95 96 if (DefaultKey) 97 usConfig |= BIT15 | (KeyType << 2); 98 else 99 usConfig |= BIT15 | (KeyType << 2) | KeyIndex; 100 101 for (i = 0; i < CAM_CONTENT_COUNT; i++) { 102 TargetCommand = i + CAM_CONTENT_COUNT * EntryNo; 103 TargetCommand |= BIT31 | BIT16; 104 105 if (i == 0) { 106 TargetContent = (u32)(*(MacAddr + 0)) << 16 | 107 (u32)(*(MacAddr + 1)) << 24 | 108 (u32)usConfig; 109 110 rtl92e_writel(dev, WCAMI, TargetContent); 111 rtl92e_writel(dev, RWCAM, TargetCommand); 112 } else if (i == 1) { 113 TargetContent = (u32)(*(MacAddr + 2)) | 114 (u32)(*(MacAddr + 3)) << 8 | 115 (u32)(*(MacAddr + 4)) << 16 | 116 (u32)(*(MacAddr + 5)) << 24; 117 rtl92e_writel(dev, WCAMI, TargetContent); 118 rtl92e_writel(dev, RWCAM, TargetCommand); 119 } else { 120 if (KeyContent != NULL) { 121 rtl92e_writel(dev, WCAMI, 122 (u32)(*(KeyContent + i - 2))); 123 rtl92e_writel(dev, RWCAM, TargetCommand); 124 udelay(100); 125 } 126 } 127 } 128 } 129 130 void rtl92e_cam_restore(struct net_device *dev) 131 { 132 u8 EntryId = 0; 133 struct r8192_priv *priv = rtllib_priv(dev); 134 u8 *MacAddr = priv->rtllib->current_network.bssid; 135 136 static u8 CAM_CONST_ADDR[4][6] = { 137 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 138 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 139 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 140 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} 141 }; 142 static u8 CAM_CONST_BROAD[] = { 143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 144 }; 145 146 if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) || 147 (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) { 148 for (EntryId = 0; EntryId < 4; EntryId++) { 149 MacAddr = CAM_CONST_ADDR[EntryId]; 150 if (priv->rtllib->swcamtable[EntryId].bused) { 151 rtl92e_set_key(dev, EntryId, EntryId, 152 priv->rtllib->pairwise_key_type, 153 MacAddr, 0, 154 (u32 *)(&priv->rtllib->swcamtable 155 [EntryId].key_buf[0])); 156 } 157 } 158 159 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) { 160 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { 161 rtl92e_set_key(dev, 4, 0, 162 priv->rtllib->pairwise_key_type, 163 (const u8 *)dev->dev_addr, 0, 164 (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); 165 } else { 166 rtl92e_set_key(dev, 4, 0, 167 priv->rtllib->pairwise_key_type, 168 MacAddr, 0, 169 (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); 170 } 171 172 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) { 173 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { 174 rtl92e_set_key(dev, 4, 0, 175 priv->rtllib->pairwise_key_type, 176 (const u8 *)dev->dev_addr, 0, 177 (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); 178 } else { 179 rtl92e_set_key(dev, 4, 0, 180 priv->rtllib->pairwise_key_type, MacAddr, 181 0, (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); 182 } 183 } 184 185 if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) { 186 MacAddr = CAM_CONST_BROAD; 187 for (EntryId = 1; EntryId < 4; EntryId++) { 188 if (priv->rtllib->swcamtable[EntryId].bused) { 189 rtl92e_set_key(dev, EntryId, EntryId, 190 priv->rtllib->group_key_type, 191 MacAddr, 0, 192 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); 193 } 194 } 195 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { 196 if (priv->rtllib->swcamtable[0].bused) { 197 rtl92e_set_key(dev, 0, 0, 198 priv->rtllib->group_key_type, 199 CAM_CONST_ADDR[0], 0, 200 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); 201 } else { 202 netdev_warn(dev, 203 "%s(): ADHOC TKIP: missing key entry.\n", 204 __func__); 205 return; 206 } 207 } 208 } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) { 209 MacAddr = CAM_CONST_BROAD; 210 for (EntryId = 1; EntryId < 4; EntryId++) { 211 if (priv->rtllib->swcamtable[EntryId].bused) { 212 rtl92e_set_key(dev, EntryId, EntryId, 213 priv->rtllib->group_key_type, 214 MacAddr, 0, 215 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); 216 } 217 } 218 219 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { 220 if (priv->rtllib->swcamtable[0].bused) { 221 rtl92e_set_key(dev, 0, 0, 222 priv->rtllib->group_key_type, 223 CAM_CONST_ADDR[0], 0, 224 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); 225 } else { 226 netdev_warn(dev, 227 "%s(): ADHOC CCMP: missing key entry.\n", 228 __func__); 229 return; 230 } 231 } 232 } 233 } 234