Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2019-2020  Realtek Corporation
0003  */
0004 
0005 #include "cam.h"
0006 #include "debug.h"
0007 #include "fw.h"
0008 #include "mac.h"
0009 
0010 static struct sk_buff *
0011 rtw89_cam_get_sec_key_cmd(struct rtw89_dev *rtwdev,
0012               struct rtw89_sec_cam_entry *sec_cam,
0013               bool ext_key)
0014 {
0015     struct sk_buff *skb;
0016     u32 cmd_len = H2C_SEC_CAM_LEN;
0017     u32 key32[4];
0018     u8 *cmd;
0019     int i, j;
0020 
0021     skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, cmd_len);
0022     if (!skb)
0023         return NULL;
0024 
0025     skb_put_zero(skb, cmd_len);
0026 
0027     for (i = 0; i < 4; i++) {
0028         j = i * 4;
0029         j += ext_key ? 16 : 0;
0030         key32[i] = FIELD_PREP(GENMASK(7, 0), sec_cam->key[j + 0]) |
0031                FIELD_PREP(GENMASK(15, 8), sec_cam->key[j + 1]) |
0032                FIELD_PREP(GENMASK(23, 16), sec_cam->key[j + 2]) |
0033                FIELD_PREP(GENMASK(31, 24), sec_cam->key[j + 3]);
0034     }
0035 
0036     cmd = skb->data;
0037     RTW89_SET_FWCMD_SEC_IDX(cmd, sec_cam->sec_cam_idx + (ext_key ? 1 : 0));
0038     RTW89_SET_FWCMD_SEC_OFFSET(cmd, sec_cam->offset);
0039     RTW89_SET_FWCMD_SEC_LEN(cmd, sec_cam->len);
0040     RTW89_SET_FWCMD_SEC_TYPE(cmd, sec_cam->type);
0041     RTW89_SET_FWCMD_SEC_EXT_KEY(cmd, ext_key);
0042     RTW89_SET_FWCMD_SEC_SPP_MODE(cmd, sec_cam->spp_mode);
0043     RTW89_SET_FWCMD_SEC_KEY0(cmd, key32[0]);
0044     RTW89_SET_FWCMD_SEC_KEY1(cmd, key32[1]);
0045     RTW89_SET_FWCMD_SEC_KEY2(cmd, key32[2]);
0046     RTW89_SET_FWCMD_SEC_KEY3(cmd, key32[3]);
0047 
0048     return skb;
0049 }
0050 
0051 static int rtw89_cam_send_sec_key_cmd(struct rtw89_dev *rtwdev,
0052                       struct rtw89_sec_cam_entry *sec_cam)
0053 {
0054     struct sk_buff *skb, *ext_skb;
0055     int ret;
0056 
0057     skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, false);
0058     if (!skb) {
0059         rtw89_err(rtwdev, "failed to get sec key command\n");
0060         return -ENOMEM;
0061     }
0062 
0063     rtw89_h2c_pkt_set_hdr(rtwdev, skb,
0064                   FWCMD_TYPE_H2C,
0065                   H2C_CAT_MAC,
0066                   H2C_CL_MAC_SEC_CAM,
0067                   H2C_FUNC_MAC_SEC_UPD, 1, 0,
0068                   H2C_SEC_CAM_LEN);
0069     ret = rtw89_h2c_tx(rtwdev, skb, false);
0070     if (ret) {
0071         rtw89_err(rtwdev, "failed to send sec key h2c: %d\n", ret);
0072         dev_kfree_skb(skb);
0073         return ret;
0074     }
0075 
0076     if (!sec_cam->ext_key)
0077         return 0;
0078 
0079     ext_skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, true);
0080     if (!ext_skb) {
0081         rtw89_err(rtwdev, "failed to get ext sec key command\n");
0082         return -ENOMEM;
0083     }
0084 
0085     rtw89_h2c_pkt_set_hdr(rtwdev, ext_skb,
0086                   FWCMD_TYPE_H2C,
0087                   H2C_CAT_MAC,
0088                   H2C_CL_MAC_SEC_CAM,
0089                   H2C_FUNC_MAC_SEC_UPD,
0090                   1, 0, H2C_SEC_CAM_LEN);
0091     ret = rtw89_h2c_tx(rtwdev, ext_skb, false);
0092     if (ret) {
0093         rtw89_err(rtwdev, "failed to send ext sec key h2c: %d\n", ret);
0094         dev_kfree_skb(ext_skb);
0095         return ret;
0096     }
0097 
0098     return 0;
0099 }
0100 
0101 static int rtw89_cam_get_avail_sec_cam(struct rtw89_dev *rtwdev,
0102                        u8 *sec_cam_idx, bool ext_key)
0103 {
0104     const struct rtw89_chip_info *chip = rtwdev->chip;
0105     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0106     u8 sec_cam_num = chip->scam_num;
0107     u8 idx = 0;
0108 
0109     if (!ext_key) {
0110         idx = find_first_zero_bit(cam_info->sec_cam_map, sec_cam_num);
0111         if (idx >= sec_cam_num)
0112             return -EBUSY;
0113 
0114         set_bit(idx, cam_info->sec_cam_map);
0115         *sec_cam_idx = idx;
0116 
0117         return 0;
0118     }
0119 
0120 again:
0121     idx = find_next_zero_bit(cam_info->sec_cam_map, sec_cam_num, idx);
0122     if (idx >= sec_cam_num - 1)
0123         return -EBUSY;
0124     /* ext keys need two cam entries for 256-bit key */
0125     if (test_bit(idx + 1, cam_info->sec_cam_map)) {
0126         idx++;
0127         goto again;
0128     }
0129 
0130     set_bit(idx, cam_info->sec_cam_map);
0131     set_bit(idx + 1, cam_info->sec_cam_map);
0132     *sec_cam_idx = idx;
0133 
0134     return 0;
0135 }
0136 
0137 static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
0138                       struct rtw89_sec_cam_entry *sec_cam,
0139                       struct ieee80211_key_conf *key,
0140                       u8 *key_idx)
0141 {
0142     u8 idx;
0143 
0144     /* RTW89_ADDR_CAM_SEC_NONE  : not enabled
0145      * RTW89_ADDR_CAM_SEC_ALL_UNI   : 0 - 6 unicast
0146      * RTW89_ADDR_CAM_SEC_NORMAL    : 0 - 1 unicast, 2 - 4 group, 5 - 6 BIP
0147      * RTW89_ADDR_CAM_SEC_4GROUP    : 0 - 1 unicast, 2 - 5 group, 6 BIP
0148      */
0149     switch (addr_cam->sec_ent_mode) {
0150     case RTW89_ADDR_CAM_SEC_NONE:
0151         return -EINVAL;
0152     case RTW89_ADDR_CAM_SEC_ALL_UNI:
0153         if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
0154             return -EINVAL;
0155         idx = find_first_zero_bit(addr_cam->sec_cam_map,
0156                       RTW89_SEC_CAM_IN_ADDR_CAM);
0157         if (idx >= RTW89_SEC_CAM_IN_ADDR_CAM)
0158             return -EBUSY;
0159         *key_idx = idx;
0160         break;
0161     case RTW89_ADDR_CAM_SEC_NORMAL:
0162         if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) {
0163             idx = find_next_zero_bit(addr_cam->sec_cam_map,
0164                          RTW89_SEC_CAM_IN_ADDR_CAM, 5);
0165             if (idx > 6)
0166                 return -EBUSY;
0167             *key_idx = idx;
0168             break;
0169         }
0170 
0171         if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
0172             idx = find_next_zero_bit(addr_cam->sec_cam_map,
0173                          RTW89_SEC_CAM_IN_ADDR_CAM, 0);
0174             if (idx > 1)
0175                 return -EBUSY;
0176             *key_idx = idx;
0177             break;
0178         }
0179 
0180         /* Group keys */
0181         idx = find_next_zero_bit(addr_cam->sec_cam_map,
0182                      RTW89_SEC_CAM_IN_ADDR_CAM, 2);
0183         if (idx > 4)
0184             return -EBUSY;
0185         *key_idx = idx;
0186         break;
0187     case RTW89_ADDR_CAM_SEC_4GROUP:
0188         if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) {
0189             if (test_bit(6, addr_cam->sec_cam_map))
0190                 return -EINVAL;
0191             *key_idx = 6;
0192             break;
0193         }
0194 
0195         if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
0196             idx = find_next_zero_bit(addr_cam->sec_cam_map,
0197                          RTW89_SEC_CAM_IN_ADDR_CAM, 0);
0198             if (idx > 1)
0199                 return -EBUSY;
0200             *key_idx = idx;
0201             break;
0202         }
0203 
0204         /* Group keys */
0205         idx = find_next_zero_bit(addr_cam->sec_cam_map,
0206                      RTW89_SEC_CAM_IN_ADDR_CAM, 2);
0207         if (idx > 5)
0208             return -EBUSY;
0209         *key_idx = idx;
0210         break;
0211     }
0212 
0213     return 0;
0214 }
0215 
0216 static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
0217                     struct ieee80211_vif *vif,
0218                     struct ieee80211_sta *sta,
0219                     struct ieee80211_key_conf *key,
0220                     struct rtw89_sec_cam_entry *sec_cam)
0221 {
0222     struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
0223     struct rtw89_vif *rtwvif;
0224     struct rtw89_addr_cam_entry *addr_cam;
0225     u8 key_idx = 0;
0226     int ret;
0227 
0228     if (!vif) {
0229         rtw89_err(rtwdev, "No iface for adding sec cam\n");
0230         return -EINVAL;
0231     }
0232 
0233     rtwvif = (struct rtw89_vif *)vif->drv_priv;
0234     addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
0235     ret = rtw89_cam_get_addr_cam_key_idx(addr_cam, sec_cam, key, &key_idx);
0236     if (ret) {
0237         rtw89_err(rtwdev, "failed to get addr cam key idx %d, %d\n",
0238               addr_cam->sec_ent_mode, sec_cam->type);
0239         return ret;
0240     }
0241 
0242     key->hw_key_idx = key_idx;
0243     addr_cam->sec_ent_keyid[key_idx] = key->keyidx;
0244     addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx;
0245     addr_cam->sec_entries[key_idx] = sec_cam;
0246     set_bit(key_idx, addr_cam->sec_cam_map);
0247     ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
0248     if (ret) {
0249         rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n",
0250               ret);
0251         return ret;
0252     }
0253     ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
0254     if (ret) {
0255         rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
0256               ret);
0257         clear_bit(key_idx, addr_cam->sec_cam_map);
0258         addr_cam->sec_entries[key_idx] = NULL;
0259         return ret;
0260     }
0261 
0262     return 0;
0263 }
0264 
0265 static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
0266                      struct ieee80211_vif *vif,
0267                      struct ieee80211_sta *sta,
0268                      struct ieee80211_key_conf *key,
0269                      u8 hw_key_type, bool ext_key)
0270 {
0271     struct rtw89_sec_cam_entry *sec_cam = NULL;
0272     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0273     u8 sec_cam_idx;
0274     int ret;
0275 
0276     /* maximum key length 256-bit */
0277     if (key->keylen > 32) {
0278         rtw89_err(rtwdev, "invalid sec key length %d\n", key->keylen);
0279         return -EINVAL;
0280     }
0281 
0282     ret = rtw89_cam_get_avail_sec_cam(rtwdev, &sec_cam_idx, ext_key);
0283     if (ret) {
0284         rtw89_warn(rtwdev, "no available sec cam: %d ext: %d\n",
0285                ret, ext_key);
0286         return ret;
0287     }
0288 
0289     sec_cam = kzalloc(sizeof(*sec_cam), GFP_KERNEL);
0290     if (!sec_cam) {
0291         ret = -ENOMEM;
0292         goto err_release_cam;
0293     }
0294 
0295     sec_cam->sec_cam_idx = sec_cam_idx;
0296     sec_cam->type = hw_key_type;
0297     sec_cam->len = RTW89_SEC_CAM_LEN;
0298     sec_cam->ext_key = ext_key;
0299     memcpy(sec_cam->key, key->key, key->keylen);
0300     ret = rtw89_cam_send_sec_key_cmd(rtwdev, sec_cam);
0301     if (ret) {
0302         rtw89_err(rtwdev, "failed to send sec key cmd: %d\n", ret);
0303         goto err_release_cam;
0304     }
0305 
0306     /* associate with addr cam */
0307     ret = rtw89_cam_attach_sec_cam(rtwdev, vif, sta, key, sec_cam);
0308     if (ret) {
0309         rtw89_err(rtwdev, "failed to attach sec cam: %d\n", ret);
0310         goto err_release_cam;
0311     }
0312 
0313     return 0;
0314 
0315 err_release_cam:
0316     kfree(sec_cam);
0317     clear_bit(sec_cam_idx, cam_info->sec_cam_map);
0318     if (ext_key)
0319         clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map);
0320 
0321     return ret;
0322 }
0323 
0324 int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
0325               struct ieee80211_vif *vif,
0326               struct ieee80211_sta *sta,
0327               struct ieee80211_key_conf *key)
0328 {
0329     const struct rtw89_chip_info *chip = rtwdev->chip;
0330     u8 hw_key_type;
0331     bool ext_key = false;
0332     int ret;
0333 
0334     switch (key->cipher) {
0335     case WLAN_CIPHER_SUITE_WEP40:
0336         hw_key_type = RTW89_SEC_KEY_TYPE_WEP40;
0337         break;
0338     case WLAN_CIPHER_SUITE_WEP104:
0339         hw_key_type = RTW89_SEC_KEY_TYPE_WEP104;
0340         break;
0341     case WLAN_CIPHER_SUITE_CCMP:
0342         hw_key_type = RTW89_SEC_KEY_TYPE_CCMP128;
0343         key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
0344         break;
0345     case WLAN_CIPHER_SUITE_CCMP_256:
0346         hw_key_type = RTW89_SEC_KEY_TYPE_CCMP256;
0347         key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
0348         ext_key = true;
0349         break;
0350     case WLAN_CIPHER_SUITE_GCMP:
0351         hw_key_type = RTW89_SEC_KEY_TYPE_GCMP128;
0352         key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
0353         break;
0354     case WLAN_CIPHER_SUITE_GCMP_256:
0355         hw_key_type = RTW89_SEC_KEY_TYPE_GCMP256;
0356         key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
0357         ext_key = true;
0358         break;
0359     default:
0360         return -EOPNOTSUPP;
0361     }
0362 
0363     if (!chip->hw_sec_hdr)
0364         key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
0365 
0366     ret = rtw89_cam_sec_key_install(rtwdev, vif, sta, key, hw_key_type,
0367                     ext_key);
0368     if (ret) {
0369         rtw89_err(rtwdev, "failed to install key type %d ext %d: %d\n",
0370               hw_key_type, ext_key, ret);
0371         return ret;
0372     }
0373 
0374     return 0;
0375 }
0376 
0377 int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
0378               struct ieee80211_vif *vif,
0379               struct ieee80211_sta *sta,
0380               struct ieee80211_key_conf *key,
0381               bool inform_fw)
0382 {
0383     struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
0384     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0385     struct rtw89_vif *rtwvif;
0386     struct rtw89_addr_cam_entry *addr_cam;
0387     struct rtw89_sec_cam_entry *sec_cam;
0388     u8 key_idx = key->hw_key_idx;
0389     u8 sec_cam_idx;
0390     int ret = 0;
0391 
0392     if (!vif) {
0393         rtw89_err(rtwdev, "No iface for deleting sec cam\n");
0394         return -EINVAL;
0395     }
0396 
0397     rtwvif = (struct rtw89_vif *)vif->drv_priv;
0398     addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
0399     sec_cam = addr_cam->sec_entries[key_idx];
0400     if (!sec_cam)
0401         return -EINVAL;
0402 
0403     /* detach sec cam from addr cam */
0404     clear_bit(key_idx, addr_cam->sec_cam_map);
0405     addr_cam->sec_entries[key_idx] = NULL;
0406     if (inform_fw) {
0407         ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
0408         if (ret)
0409             rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret);
0410         ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
0411         if (ret)
0412             rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
0413     }
0414 
0415     /* clear valid bit in addr cam will disable sec cam,
0416      * so we don't need to send H2C command again
0417      */
0418     sec_cam_idx = sec_cam->sec_cam_idx;
0419     clear_bit(sec_cam_idx, cam_info->sec_cam_map);
0420     if (sec_cam->ext_key)
0421         clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map);
0422 
0423     kfree(sec_cam);
0424 
0425     return ret;
0426 }
0427 
0428 static void rtw89_cam_reset_key_iter(struct ieee80211_hw *hw,
0429                      struct ieee80211_vif *vif,
0430                      struct ieee80211_sta *sta,
0431                      struct ieee80211_key_conf *key,
0432                      void *data)
0433 {
0434     struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
0435 
0436     rtw89_cam_sec_key_del(rtwdev, vif, sta, key, false);
0437 }
0438 
0439 void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev,
0440                    struct rtw89_addr_cam_entry *addr_cam)
0441 {
0442     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0443 
0444     addr_cam->valid = false;
0445     clear_bit(addr_cam->addr_cam_idx, cam_info->addr_cam_map);
0446 }
0447 
0448 void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev,
0449                 struct rtw89_bssid_cam_entry *bssid_cam)
0450 {
0451     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0452 
0453     bssid_cam->valid = false;
0454     clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map);
0455 }
0456 
0457 void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
0458 {
0459     struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
0460     struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
0461 
0462     rtw89_cam_deinit_addr_cam(rtwdev, addr_cam);
0463     rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam);
0464 }
0465 
0466 void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev)
0467 {
0468     rcu_read_lock();
0469     ieee80211_iter_keys_rcu(rtwdev->hw, NULL, rtw89_cam_reset_key_iter, rtwdev);
0470     rcu_read_unlock();
0471 }
0472 
0473 static int rtw89_cam_get_avail_addr_cam(struct rtw89_dev *rtwdev,
0474                     u8 *addr_cam_idx)
0475 {
0476     const struct rtw89_chip_info *chip = rtwdev->chip;
0477     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0478     u8 addr_cam_num = chip->acam_num;
0479     u8 idx;
0480 
0481     idx = find_first_zero_bit(cam_info->addr_cam_map, addr_cam_num);
0482     if (idx >= addr_cam_num)
0483         return -EBUSY;
0484 
0485     set_bit(idx, cam_info->addr_cam_map);
0486     *addr_cam_idx = idx;
0487 
0488     return 0;
0489 }
0490 
0491 int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
0492                 struct rtw89_addr_cam_entry *addr_cam,
0493                 const struct rtw89_bssid_cam_entry *bssid_cam)
0494 {
0495     u8 addr_cam_idx;
0496     int i;
0497     int ret;
0498 
0499     if (unlikely(addr_cam->valid)) {
0500         rtw89_debug(rtwdev, RTW89_DBG_FW,
0501                 "addr cam is already valid; skip init\n");
0502         return 0;
0503     }
0504 
0505     ret = rtw89_cam_get_avail_addr_cam(rtwdev, &addr_cam_idx);
0506     if (ret) {
0507         rtw89_err(rtwdev, "failed to get available addr cam\n");
0508         return ret;
0509     }
0510 
0511     addr_cam->addr_cam_idx = addr_cam_idx;
0512     addr_cam->len = ADDR_CAM_ENT_SIZE;
0513     addr_cam->offset = 0;
0514     addr_cam->valid = true;
0515     addr_cam->addr_mask = 0;
0516     addr_cam->mask_sel = RTW89_NO_MSK;
0517     addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL;
0518     bitmap_zero(addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM);
0519 
0520     for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) {
0521         addr_cam->sec_ent_keyid[i] = 0;
0522         addr_cam->sec_ent[i] = 0;
0523     }
0524 
0525     /* associate addr cam with bssid cam */
0526     addr_cam->bssid_cam_idx = bssid_cam->bssid_cam_idx;
0527 
0528     return 0;
0529 }
0530 
0531 static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev,
0532                      u8 *bssid_cam_idx)
0533 {
0534     const struct rtw89_chip_info *chip = rtwdev->chip;
0535     struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
0536     u8 bssid_cam_num = chip->bcam_num;
0537     u8 idx;
0538 
0539     idx = find_first_zero_bit(cam_info->bssid_cam_map, bssid_cam_num);
0540     if (idx >= bssid_cam_num)
0541         return -EBUSY;
0542 
0543     set_bit(idx, cam_info->bssid_cam_map);
0544     *bssid_cam_idx = idx;
0545 
0546     return 0;
0547 }
0548 
0549 int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
0550                  struct rtw89_vif *rtwvif,
0551                  struct rtw89_bssid_cam_entry *bssid_cam,
0552                  const u8 *bssid)
0553 {
0554     u8 bssid_cam_idx;
0555     int ret;
0556 
0557     if (unlikely(bssid_cam->valid)) {
0558         rtw89_debug(rtwdev, RTW89_DBG_FW,
0559                 "bssid cam is already valid; skip init\n");
0560         return 0;
0561     }
0562 
0563     ret = rtw89_cam_get_avail_bssid_cam(rtwdev, &bssid_cam_idx);
0564     if (ret) {
0565         rtw89_err(rtwdev, "failed to get available bssid cam\n");
0566         return ret;
0567     }
0568 
0569     bssid_cam->bssid_cam_idx = bssid_cam_idx;
0570     bssid_cam->phy_idx = rtwvif->phy_idx;
0571     bssid_cam->len = BSSID_CAM_ENT_SIZE;
0572     bssid_cam->offset = 0;
0573     bssid_cam->valid = true;
0574     ether_addr_copy(bssid_cam->bssid, bssid);
0575 
0576     return 0;
0577 }
0578 
0579 void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
0580 {
0581     struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
0582 
0583     ether_addr_copy(bssid_cam->bssid, rtwvif->bssid);
0584 }
0585 
0586 int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
0587 {
0588     struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
0589     struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
0590     int ret;
0591 
0592     ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid);
0593     if (ret) {
0594         rtw89_err(rtwdev, "failed to init bssid cam\n");
0595         return ret;
0596     }
0597 
0598     ret = rtw89_cam_init_addr_cam(rtwdev, addr_cam, bssid_cam);
0599     if (ret) {
0600         rtw89_err(rtwdev, "failed to init addr cam\n");
0601         return ret;
0602     }
0603 
0604     return 0;
0605 }
0606 
0607 int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
0608                   struct rtw89_vif *rtwvif,
0609                   struct rtw89_sta *rtwsta, u8 *cmd)
0610 {
0611     struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
0612     struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta);
0613     u8 bss_color = vif->bss_conf.he_bss_color.color;
0614     u8 bss_mask;
0615 
0616     if (vif->bss_conf.nontransmitted)
0617         bss_mask = RTW89_BSSID_MATCH_5_BYTES;
0618     else
0619         bss_mask = RTW89_BSSID_MATCH_ALL;
0620 
0621     FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx);
0622     FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset);
0623     FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len);
0624     FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid);
0625     FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask);
0626     FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx);
0627     FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color);
0628 
0629     FWCMD_SET_ADDR_BSSID_BSSID0(cmd, bssid_cam->bssid[0]);
0630     FWCMD_SET_ADDR_BSSID_BSSID1(cmd, bssid_cam->bssid[1]);
0631     FWCMD_SET_ADDR_BSSID_BSSID2(cmd, bssid_cam->bssid[2]);
0632     FWCMD_SET_ADDR_BSSID_BSSID3(cmd, bssid_cam->bssid[3]);
0633     FWCMD_SET_ADDR_BSSID_BSSID4(cmd, bssid_cam->bssid[4]);
0634     FWCMD_SET_ADDR_BSSID_BSSID5(cmd, bssid_cam->bssid[5]);
0635 
0636     return 0;
0637 }
0638 
0639 static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr)
0640 {
0641     u8 hash = 0;
0642     u8 i;
0643 
0644     for (i = start; i < ETH_ALEN; i++)
0645         hash ^= addr[i];
0646 
0647     return hash;
0648 }
0649 
0650 void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
0651                   struct rtw89_vif *rtwvif,
0652                   struct rtw89_sta *rtwsta,
0653                   const u8 *scan_mac_addr,
0654                   u8 *cmd)
0655 {
0656     struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
0657     struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
0658     struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
0659     const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr;
0660     u8 sma_hash, tma_hash, addr_msk_start;
0661     u8 sma_start = 0;
0662     u8 tma_start = 0;
0663     u8 *tma = sta ? sta->addr : rtwvif->bssid;
0664 
0665     if (addr_cam->addr_mask != 0) {
0666         addr_msk_start = __ffs(addr_cam->addr_mask);
0667         if (addr_cam->mask_sel == RTW89_SMA)
0668             sma_start = addr_msk_start;
0669         else if (addr_cam->mask_sel == RTW89_TMA)
0670             tma_start = addr_msk_start;
0671     }
0672     sma_hash = rtw89_cam_addr_hash(sma_start, sma);
0673     tma_hash = rtw89_cam_addr_hash(tma_start, tma);
0674 
0675     FWCMD_SET_ADDR_IDX(cmd, addr_cam->addr_cam_idx);
0676     FWCMD_SET_ADDR_OFFSET(cmd, addr_cam->offset);
0677     FWCMD_SET_ADDR_LEN(cmd, addr_cam->len);
0678 
0679     FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid);
0680     FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type);
0681     FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond);
0682     FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule);
0683     FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx);
0684     FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask);
0685     FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel);
0686     FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash);
0687     FWCMD_SET_ADDR_TMA_HASH(cmd, tma_hash);
0688 
0689     FWCMD_SET_ADDR_BSSID_CAM_IDX(cmd, addr_cam->bssid_cam_idx);
0690 
0691     FWCMD_SET_ADDR_SMA0(cmd, sma[0]);
0692     FWCMD_SET_ADDR_SMA1(cmd, sma[1]);
0693     FWCMD_SET_ADDR_SMA2(cmd, sma[2]);
0694     FWCMD_SET_ADDR_SMA3(cmd, sma[3]);
0695     FWCMD_SET_ADDR_SMA4(cmd, sma[4]);
0696     FWCMD_SET_ADDR_SMA5(cmd, sma[5]);
0697 
0698     FWCMD_SET_ADDR_TMA0(cmd, tma[0]);
0699     FWCMD_SET_ADDR_TMA1(cmd, tma[1]);
0700     FWCMD_SET_ADDR_TMA2(cmd, tma[2]);
0701     FWCMD_SET_ADDR_TMA3(cmd, tma[3]);
0702     FWCMD_SET_ADDR_TMA4(cmd, tma[4]);
0703     FWCMD_SET_ADDR_TMA5(cmd, tma[5]);
0704 
0705     FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port);
0706     FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port);
0707     FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger);
0708     FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop);
0709     FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind);
0710     FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind);
0711     FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
0712     if (rtwvif->net_type == RTW89_NET_TYPE_INFRA)
0713         FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff);
0714     else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
0715         FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0);
0716     FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern);
0717     FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc);
0718     FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic);
0719     FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi);
0720     FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode);
0721     FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]);
0722     FWCMD_SET_ADDR_SEC_ENT1_KEYID(cmd, addr_cam->sec_ent_keyid[1]);
0723     FWCMD_SET_ADDR_SEC_ENT2_KEYID(cmd, addr_cam->sec_ent_keyid[2]);
0724     FWCMD_SET_ADDR_SEC_ENT3_KEYID(cmd, addr_cam->sec_ent_keyid[3]);
0725     FWCMD_SET_ADDR_SEC_ENT4_KEYID(cmd, addr_cam->sec_ent_keyid[4]);
0726     FWCMD_SET_ADDR_SEC_ENT5_KEYID(cmd, addr_cam->sec_ent_keyid[5]);
0727     FWCMD_SET_ADDR_SEC_ENT6_KEYID(cmd, addr_cam->sec_ent_keyid[6]);
0728 
0729     FWCMD_SET_ADDR_SEC_ENT_VALID(cmd, addr_cam->sec_cam_map[0] & 0xff);
0730     FWCMD_SET_ADDR_SEC_ENT0(cmd, addr_cam->sec_ent[0]);
0731     FWCMD_SET_ADDR_SEC_ENT1(cmd, addr_cam->sec_ent[1]);
0732     FWCMD_SET_ADDR_SEC_ENT2(cmd, addr_cam->sec_ent[2]);
0733     FWCMD_SET_ADDR_SEC_ENT3(cmd, addr_cam->sec_ent[3]);
0734     FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]);
0735     FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]);
0736     FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]);
0737 }
0738 
0739 void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
0740                      struct rtw89_vif *rtwvif,
0741                      struct rtw89_sta *rtwsta,
0742                      u8 *cmd)
0743 {
0744     struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
0745 
0746     SET_DCTL_MACID_V1(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
0747     SET_DCTL_OPERATION_V1(cmd, 1);
0748 
0749     SET_DCTL_SEC_ENT0_KEYID_V1(cmd, addr_cam->sec_ent_keyid[0]);
0750     SET_DCTL_SEC_ENT1_KEYID_V1(cmd, addr_cam->sec_ent_keyid[1]);
0751     SET_DCTL_SEC_ENT2_KEYID_V1(cmd, addr_cam->sec_ent_keyid[2]);
0752     SET_DCTL_SEC_ENT3_KEYID_V1(cmd, addr_cam->sec_ent_keyid[3]);
0753     SET_DCTL_SEC_ENT4_KEYID_V1(cmd, addr_cam->sec_ent_keyid[4]);
0754     SET_DCTL_SEC_ENT5_KEYID_V1(cmd, addr_cam->sec_ent_keyid[5]);
0755     SET_DCTL_SEC_ENT6_KEYID_V1(cmd, addr_cam->sec_ent_keyid[6]);
0756 
0757     SET_DCTL_SEC_ENT_VALID_V1(cmd, addr_cam->sec_cam_map[0] & 0xff);
0758     SET_DCTL_SEC_ENT0_V1(cmd, addr_cam->sec_ent[0]);
0759     SET_DCTL_SEC_ENT1_V1(cmd, addr_cam->sec_ent[1]);
0760     SET_DCTL_SEC_ENT2_V1(cmd, addr_cam->sec_ent[2]);
0761     SET_DCTL_SEC_ENT3_V1(cmd, addr_cam->sec_ent[3]);
0762     SET_DCTL_SEC_ENT4_V1(cmd, addr_cam->sec_ent[4]);
0763     SET_DCTL_SEC_ENT5_V1(cmd, addr_cam->sec_ent[5]);
0764     SET_DCTL_SEC_ENT6_V1(cmd, addr_cam->sec_ent[6]);
0765 }