sec.c 3.5 KB

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