cam.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // SPDX-License-Identifier: GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Copyright(c) 2009-2012 Realtek Corporation.
  5. *
  6. * Contact Information:
  7. * wlanfae <wlanfae@realtek.com>
  8. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  9. * Hsinchu 300, Taiwan.
  10. *
  11. * Larry Finger <Larry.Finger@lwfinger.net>
  12. *
  13. *****************************************************************************/
  14. #include "wifi.h"
  15. #include "cam.h"
  16. #include <linux/export.h>
  17. void rtl_cam_reset_sec_info(struct ieee80211_hw *hw)
  18. {
  19. struct rtl_priv *rtlpriv = rtl_priv(hw);
  20. rtlpriv->sec.use_defaultkey = false;
  21. rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION;
  22. rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION;
  23. memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN);
  24. memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE);
  25. rtlpriv->sec.pairwise_key = NULL;
  26. }
  27. static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
  28. u8 *mac_addr, u8 *key_cont_128, u16 us_config)
  29. {
  30. struct rtl_priv *rtlpriv = rtl_priv(hw);
  31. u32 target_command;
  32. u32 target_content = 0;
  33. int entry_i;
  34. RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :",
  35. key_cont_128, 16);
  36. /* 0-1 config + mac, 2-5 fill 128key,6-7 are reserved */
  37. for (entry_i = CAM_CONTENT_COUNT - 1; entry_i >= 0; entry_i--) {
  38. target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
  39. target_command = target_command | BIT(31) | BIT(16);
  40. if (entry_i == 0) {
  41. target_content = (u32)(*(mac_addr + 0)) << 16 |
  42. (u32)(*(mac_addr + 1)) << 24 |
  43. (u32)us_config;
  44. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
  45. target_content);
  46. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
  47. target_command);
  48. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  49. "WRITE %x: %x\n",
  50. rtlpriv->cfg->maps[WCAMI], target_content);
  51. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  52. "The Key ID is %d\n", entry_no);
  53. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  54. "WRITE %x: %x\n",
  55. rtlpriv->cfg->maps[RWCAM], target_command);
  56. } else if (entry_i == 1) {
  57. target_content = (u32)(*(mac_addr + 5)) << 24 |
  58. (u32)(*(mac_addr + 4)) << 16 |
  59. (u32)(*(mac_addr + 3)) << 8 |
  60. (u32)(*(mac_addr + 2));
  61. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
  62. target_content);
  63. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
  64. target_command);
  65. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  66. "WRITE A4: %x\n", target_content);
  67. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  68. "WRITE A0: %x\n", target_command);
  69. } else {
  70. target_content =
  71. (u32)(*(key_cont_128 + (entry_i * 4 - 8) + 3)) <<
  72. 24 | (u32)(*(key_cont_128 + (entry_i * 4 - 8) + 2))
  73. << 16 |
  74. (u32)(*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8
  75. | (u32)(*(key_cont_128 + (entry_i * 4 - 8) + 0));
  76. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
  77. target_content);
  78. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
  79. target_command);
  80. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  81. "WRITE A4: %x\n", target_content);
  82. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  83. "WRITE A0: %x\n", target_command);
  84. }
  85. }
  86. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  87. "after set key, usconfig:%x\n", us_config);
  88. }
  89. u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
  90. u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
  91. u32 ul_default_key, u8 *key_content)
  92. {
  93. u32 us_config;
  94. struct rtl_priv *rtlpriv = rtl_priv(hw);
  95. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  96. "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
  97. ul_entry_idx, ul_key_id, ul_enc_alg,
  98. ul_default_key, mac_addr);
  99. if (ul_key_id == TOTAL_CAM_ENTRY) {
  100. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  101. "ulKeyId exceed!\n");
  102. return 0;
  103. }
  104. if (ul_default_key == 1)
  105. us_config = CFG_VALID | ((u16)(ul_enc_alg) << 2);
  106. else
  107. us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id;
  108. rtl_cam_program_entry(hw, ul_entry_idx, mac_addr,
  109. (u8 *)key_content, us_config);
  110. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "end\n");
  111. return 1;
  112. }
  113. int rtl_cam_delete_one_entry(struct ieee80211_hw *hw,
  114. u8 *mac_addr, u32 ul_key_id)
  115. {
  116. u32 ul_command;
  117. struct rtl_priv *rtlpriv = rtl_priv(hw);
  118. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id);
  119. ul_command = ul_key_id * CAM_CONTENT_COUNT;
  120. ul_command = ul_command | BIT(31) | BIT(16);
  121. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0);
  122. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
  123. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  124. "%s(): WRITE A4: %x\n", __func__, 0);
  125. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  126. "%s(): WRITE A0: %x\n", __func__, ul_command);
  127. return 0;
  128. }
  129. void rtl_cam_reset_all_entry(struct ieee80211_hw *hw)
  130. {
  131. u32 ul_command;
  132. struct rtl_priv *rtlpriv = rtl_priv(hw);
  133. ul_command = BIT(31) | BIT(30);
  134. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
  135. }
  136. void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index)
  137. {
  138. struct rtl_priv *rtlpriv = rtl_priv(hw);
  139. u32 ul_command;
  140. u32 ul_content;
  141. u32 ul_enc_algo;
  142. switch (rtlpriv->sec.pairwise_enc_algorithm) {
  143. case WEP40_ENCRYPTION:
  144. ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
  145. break;
  146. case WEP104_ENCRYPTION:
  147. ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
  148. break;
  149. case TKIP_ENCRYPTION:
  150. ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
  151. break;
  152. case AESCCMP_ENCRYPTION:
  153. ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
  154. break;
  155. default:
  156. ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
  157. }
  158. ul_content = (uc_index & 3) | ((u16)(ul_enc_algo) << 2);
  159. ul_content |= BIT(15);
  160. ul_command = CAM_CONTENT_COUNT * uc_index;
  161. ul_command = ul_command | BIT(31) | BIT(16);
  162. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
  163. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
  164. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  165. "%s(): WRITE A4: %x\n", __func__, ul_content);
  166. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  167. "%s(): WRITE A0: %x\n", __func__, ul_command);
  168. }
  169. void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index)
  170. {
  171. struct rtl_priv *rtlpriv = rtl_priv(hw);
  172. u32 ul_command;
  173. u32 ul_content;
  174. u32 ul_encalgo;
  175. u8 entry_i;
  176. switch (rtlpriv->sec.pairwise_enc_algorithm) {
  177. case WEP40_ENCRYPTION:
  178. ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
  179. break;
  180. case WEP104_ENCRYPTION:
  181. ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
  182. break;
  183. case TKIP_ENCRYPTION:
  184. ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
  185. break;
  186. case AESCCMP_ENCRYPTION:
  187. ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
  188. break;
  189. default:
  190. ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
  191. }
  192. for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
  193. if (entry_i == 0) {
  194. ul_content =
  195. (uc_index & 0x03) | ((u16)(ul_encalgo) << 2);
  196. ul_content |= BIT(15);
  197. } else {
  198. ul_content = 0;
  199. }
  200. ul_command = CAM_CONTENT_COUNT * uc_index + entry_i;
  201. ul_command = ul_command | BIT(31) | BIT(16);
  202. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
  203. rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
  204. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  205. "%s(): WRITE A4: %x\n", __func__, ul_content);
  206. RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
  207. "%s(): WRITE A0: %x\n", __func__, ul_command);
  208. }
  209. }
  210. u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr)
  211. {
  212. struct rtl_priv *rtlpriv = rtl_priv(hw);
  213. u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4;
  214. u8 entry_idx = 0;
  215. u8 i, *addr;
  216. if (!sta_addr) {
  217. pr_err("sta_addr is NULL.\n");
  218. return TOTAL_CAM_ENTRY;
  219. }
  220. /* Does STA already exist? */
  221. for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
  222. addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
  223. if (ether_addr_equal_unaligned(addr, sta_addr))
  224. return i;
  225. }
  226. /* Get a free CAM entry. */
  227. for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) {
  228. if ((bitmap & BIT(0)) == 0) {
  229. pr_err("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n",
  230. rtlpriv->sec.hwsec_cam_bitmap, entry_idx);
  231. rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx;
  232. memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx],
  233. sta_addr, ETH_ALEN);
  234. return entry_idx;
  235. }
  236. bitmap = bitmap >> 1;
  237. }
  238. return TOTAL_CAM_ENTRY;
  239. }
  240. void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
  241. {
  242. struct rtl_priv *rtlpriv = rtl_priv(hw);
  243. u32 bitmap;
  244. u8 i, *addr;
  245. if (!sta_addr) {
  246. pr_err("sta_addr is NULL.\n");
  247. return;
  248. }
  249. if (is_zero_ether_addr(sta_addr)) {
  250. pr_err("sta_addr is %pM\n", sta_addr);
  251. return;
  252. }
  253. /* Does STA already exist? */
  254. for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
  255. addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
  256. bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i;
  257. if (((bitmap & BIT(0)) == BIT(0)) &&
  258. (ether_addr_equal_unaligned(addr, sta_addr))) {
  259. /* Remove from HW Security CAM */
  260. eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
  261. rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
  262. RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
  263. "&&&&&&&&&del entry %d\n", i);
  264. }
  265. }
  266. }