The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/rtw89/cam.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
    2 /* Copyright(c) 2019-2020  Realtek Corporation
    3  */
    4 
    5 #include "cam.h"
    6 #include "debug.h"
    7 #include "fw.h"
    8 #include "mac.h"
    9 
   10 static struct sk_buff *
   11 rtw89_cam_get_sec_key_cmd(struct rtw89_dev *rtwdev,
   12                           struct rtw89_sec_cam_entry *sec_cam,
   13                           bool ext_key)
   14 {
   15         struct sk_buff *skb;
   16         u32 cmd_len = H2C_SEC_CAM_LEN;
   17         u32 key32[4];
   18         u8 *cmd;
   19         int i, j;
   20 
   21         skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, cmd_len);
   22         if (!skb)
   23                 return NULL;
   24 
   25         skb_put_zero(skb, cmd_len);
   26 
   27         for (i = 0; i < 4; i++) {
   28                 j = i * 4;
   29                 j += ext_key ? 16 : 0;
   30                 key32[i] = FIELD_PREP(GENMASK(7, 0), sec_cam->key[j + 0]) |
   31                            FIELD_PREP(GENMASK(15, 8), sec_cam->key[j + 1]) |
   32                            FIELD_PREP(GENMASK(23, 16), sec_cam->key[j + 2]) |
   33                            FIELD_PREP(GENMASK(31, 24), sec_cam->key[j + 3]);
   34         }
   35 
   36         cmd = skb->data;
   37         RTW89_SET_FWCMD_SEC_IDX(cmd, sec_cam->sec_cam_idx + (ext_key ? 1 : 0));
   38         RTW89_SET_FWCMD_SEC_OFFSET(cmd, sec_cam->offset);
   39         RTW89_SET_FWCMD_SEC_LEN(cmd, sec_cam->len);
   40         RTW89_SET_FWCMD_SEC_TYPE(cmd, sec_cam->type);
   41         RTW89_SET_FWCMD_SEC_EXT_KEY(cmd, ext_key);
   42         RTW89_SET_FWCMD_SEC_SPP_MODE(cmd, sec_cam->spp_mode);
   43         RTW89_SET_FWCMD_SEC_KEY0(cmd, key32[0]);
   44         RTW89_SET_FWCMD_SEC_KEY1(cmd, key32[1]);
   45         RTW89_SET_FWCMD_SEC_KEY2(cmd, key32[2]);
   46         RTW89_SET_FWCMD_SEC_KEY3(cmd, key32[3]);
   47 
   48         return skb;
   49 }
   50 
   51 static int rtw89_cam_send_sec_key_cmd(struct rtw89_dev *rtwdev,
   52                                       struct rtw89_sec_cam_entry *sec_cam)
   53 {
   54         struct sk_buff *skb, *ext_skb;
   55         int ret;
   56 
   57         skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, false);
   58         if (!skb) {
   59                 rtw89_err(rtwdev, "failed to get sec key command\n");
   60                 return -ENOMEM;
   61         }
   62 
   63         rtw89_h2c_pkt_set_hdr(rtwdev, skb,
   64                               FWCMD_TYPE_H2C,
   65                               H2C_CAT_MAC,
   66                               H2C_CL_MAC_SEC_CAM,
   67                               H2C_FUNC_MAC_SEC_UPD, 1, 0,
   68                               H2C_SEC_CAM_LEN);
   69         ret = rtw89_h2c_tx(rtwdev, skb, false);
   70         if (ret) {
   71                 rtw89_err(rtwdev, "failed to send sec key h2c: %d\n", ret);
   72                 dev_kfree_skb(skb);
   73                 return ret;
   74         }
   75 
   76         if (!sec_cam->ext_key)
   77                 return 0;
   78 
   79         ext_skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, true);
   80         if (!ext_skb) {
   81                 rtw89_err(rtwdev, "failed to get ext sec key command\n");
   82                 return -ENOMEM;
   83         }
   84 
   85         rtw89_h2c_pkt_set_hdr(rtwdev, ext_skb,
   86                               FWCMD_TYPE_H2C,
   87                               H2C_CAT_MAC,
   88                               H2C_CL_MAC_SEC_CAM,
   89                               H2C_FUNC_MAC_SEC_UPD,
   90                               1, 0, H2C_SEC_CAM_LEN);
   91         ret = rtw89_h2c_tx(rtwdev, ext_skb, false);
   92         if (ret) {
   93                 rtw89_err(rtwdev, "failed to send ext sec key h2c: %d\n", ret);
   94                 dev_kfree_skb(ext_skb);
   95                 return ret;
   96         }
   97 
   98         return 0;
   99 }
  100 
  101 static int rtw89_cam_get_avail_sec_cam(struct rtw89_dev *rtwdev,
  102                                        u8 *sec_cam_idx, bool ext_key)
  103 {
  104         const struct rtw89_chip_info *chip = rtwdev->chip;
  105         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  106         u8 sec_cam_num = chip->scam_num;
  107         u8 idx = 0;
  108 
  109         if (!ext_key) {
  110                 idx = find_first_zero_bit(cam_info->sec_cam_map, sec_cam_num);
  111                 if (idx >= sec_cam_num)
  112                         return -EBUSY;
  113 
  114                 set_bit(idx, cam_info->sec_cam_map);
  115                 *sec_cam_idx = idx;
  116 
  117                 return 0;
  118         }
  119 
  120 again:
  121         idx = find_next_zero_bit(cam_info->sec_cam_map, sec_cam_num, idx);
  122         if (idx >= sec_cam_num - 1)
  123                 return -EBUSY;
  124         /* ext keys need two cam entries for 256-bit key */
  125         if (test_bit(idx + 1, cam_info->sec_cam_map)) {
  126                 idx++;
  127                 goto again;
  128         }
  129 
  130         set_bit(idx, cam_info->sec_cam_map);
  131         set_bit(idx + 1, cam_info->sec_cam_map);
  132         *sec_cam_idx = idx;
  133 
  134         return 0;
  135 }
  136 
  137 static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
  138                                           struct rtw89_sec_cam_entry *sec_cam,
  139                                           struct ieee80211_key_conf *key,
  140                                           u8 *key_idx)
  141 {
  142         u8 idx;
  143 
  144         /* RTW89_ADDR_CAM_SEC_NONE      : not enabled
  145          * RTW89_ADDR_CAM_SEC_ALL_UNI   : 0 - 6 unicast
  146          * RTW89_ADDR_CAM_SEC_NORMAL    : 0 - 1 unicast, 2 - 4 group, 5 - 6 BIP
  147          * RTW89_ADDR_CAM_SEC_4GROUP    : 0 - 1 unicast, 2 - 5 group, 6 BIP
  148          */
  149         switch (addr_cam->sec_ent_mode) {
  150         case RTW89_ADDR_CAM_SEC_NONE:
  151                 return -EINVAL;
  152         case RTW89_ADDR_CAM_SEC_ALL_UNI:
  153                 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
  154                         return -EINVAL;
  155                 idx = find_first_zero_bit(addr_cam->sec_cam_map,
  156                                           RTW89_SEC_CAM_IN_ADDR_CAM);
  157                 if (idx >= RTW89_SEC_CAM_IN_ADDR_CAM)
  158                         return -EBUSY;
  159                 *key_idx = idx;
  160                 break;
  161         case RTW89_ADDR_CAM_SEC_NORMAL:
  162                 if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) {
  163                         idx = find_next_zero_bit(addr_cam->sec_cam_map,
  164                                                  RTW89_SEC_CAM_IN_ADDR_CAM, 5);
  165                         if (idx > 6)
  166                                 return -EBUSY;
  167                         *key_idx = idx;
  168                         break;
  169                 }
  170 
  171                 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
  172                         idx = find_next_zero_bit(addr_cam->sec_cam_map,
  173                                                  RTW89_SEC_CAM_IN_ADDR_CAM, 0);
  174                         if (idx > 1)
  175                                 return -EBUSY;
  176                         *key_idx = idx;
  177                         break;
  178                 }
  179 
  180                 /* Group keys */
  181                 idx = find_next_zero_bit(addr_cam->sec_cam_map,
  182                                          RTW89_SEC_CAM_IN_ADDR_CAM, 2);
  183                 if (idx > 4)
  184                         return -EBUSY;
  185                 *key_idx = idx;
  186                 break;
  187         case RTW89_ADDR_CAM_SEC_4GROUP:
  188                 if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) {
  189                         if (test_bit(6, addr_cam->sec_cam_map))
  190                                 return -EINVAL;
  191                         *key_idx = 6;
  192                         break;
  193                 }
  194 
  195                 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
  196                         idx = find_next_zero_bit(addr_cam->sec_cam_map,
  197                                                  RTW89_SEC_CAM_IN_ADDR_CAM, 0);
  198                         if (idx > 1)
  199                                 return -EBUSY;
  200                         *key_idx = idx;
  201                         break;
  202                 }
  203 
  204                 /* Group keys */
  205                 idx = find_next_zero_bit(addr_cam->sec_cam_map,
  206                                          RTW89_SEC_CAM_IN_ADDR_CAM, 2);
  207                 if (idx > 5)
  208                         return -EBUSY;
  209                 *key_idx = idx;
  210                 break;
  211         }
  212 
  213         return 0;
  214 }
  215 
  216 static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
  217                                     struct ieee80211_vif *vif,
  218                                     struct ieee80211_sta *sta,
  219                                     struct ieee80211_key_conf *key,
  220                                     struct rtw89_sec_cam_entry *sec_cam)
  221 {
  222         struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
  223         struct rtw89_vif *rtwvif;
  224         struct rtw89_addr_cam_entry *addr_cam;
  225         u8 key_idx = 0;
  226         int ret;
  227 
  228         if (!vif) {
  229                 rtw89_err(rtwdev, "No iface for adding sec cam\n");
  230                 return -EINVAL;
  231         }
  232 
  233         rtwvif = (struct rtw89_vif *)vif->drv_priv;
  234         addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
  235         ret = rtw89_cam_get_addr_cam_key_idx(addr_cam, sec_cam, key, &key_idx);
  236         if (ret) {
  237                 rtw89_err(rtwdev, "failed to get addr cam key idx %d, %d\n",
  238                           addr_cam->sec_ent_mode, sec_cam->type);
  239                 return ret;
  240         }
  241 
  242         key->hw_key_idx = key_idx;
  243         addr_cam->sec_ent_keyid[key_idx] = key->keyidx;
  244         addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx;
  245         addr_cam->sec_entries[key_idx] = sec_cam;
  246         set_bit(key_idx, addr_cam->sec_cam_map);
  247         ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
  248         if (ret) {
  249                 rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n",
  250                           ret);
  251                 return ret;
  252         }
  253         ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
  254         if (ret) {
  255                 rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n",
  256                           ret);
  257                 clear_bit(key_idx, addr_cam->sec_cam_map);
  258                 addr_cam->sec_entries[key_idx] = NULL;
  259                 return ret;
  260         }
  261 
  262         return 0;
  263 }
  264 
  265 static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
  266                                      struct ieee80211_vif *vif,
  267                                      struct ieee80211_sta *sta,
  268                                      struct ieee80211_key_conf *key,
  269                                      u8 hw_key_type, bool ext_key)
  270 {
  271         struct rtw89_sec_cam_entry *sec_cam = NULL;
  272         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  273         u8 sec_cam_idx;
  274         int ret;
  275 
  276         /* maximum key length 256-bit */
  277         if (key->keylen > 32) {
  278                 rtw89_err(rtwdev, "invalid sec key length %d\n", key->keylen);
  279                 return -EINVAL;
  280         }
  281 
  282         ret = rtw89_cam_get_avail_sec_cam(rtwdev, &sec_cam_idx, ext_key);
  283         if (ret) {
  284                 rtw89_warn(rtwdev, "no available sec cam: %d ext: %d\n",
  285                            ret, ext_key);
  286                 return ret;
  287         }
  288 
  289         sec_cam = kzalloc(sizeof(*sec_cam), GFP_KERNEL);
  290         if (!sec_cam) {
  291                 ret = -ENOMEM;
  292                 goto err_release_cam;
  293         }
  294 
  295         sec_cam->sec_cam_idx = sec_cam_idx;
  296         sec_cam->type = hw_key_type;
  297         sec_cam->len = RTW89_SEC_CAM_LEN;
  298         sec_cam->ext_key = ext_key;
  299         memcpy(sec_cam->key, key->key, key->keylen);
  300         ret = rtw89_cam_send_sec_key_cmd(rtwdev, sec_cam);
  301         if (ret) {
  302                 rtw89_err(rtwdev, "failed to send sec key cmd: %d\n", ret);
  303                 goto err_release_cam;
  304         }
  305 
  306         /* associate with addr cam */
  307         ret = rtw89_cam_attach_sec_cam(rtwdev, vif, sta, key, sec_cam);
  308         if (ret) {
  309                 rtw89_err(rtwdev, "failed to attach sec cam: %d\n", ret);
  310                 goto err_release_cam;
  311         }
  312 
  313         return 0;
  314 
  315 err_release_cam:
  316         kfree(sec_cam);
  317         clear_bit(sec_cam_idx, cam_info->sec_cam_map);
  318         if (ext_key)
  319                 clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map);
  320 
  321         return ret;
  322 }
  323 
  324 int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
  325                           struct ieee80211_vif *vif,
  326                           struct ieee80211_sta *sta,
  327                           struct ieee80211_key_conf *key)
  328 {
  329         const struct rtw89_chip_info *chip = rtwdev->chip;
  330         u8 hw_key_type;
  331         bool ext_key = false;
  332         int ret;
  333 
  334         switch (key->cipher) {
  335         case WLAN_CIPHER_SUITE_WEP40:
  336                 hw_key_type = RTW89_SEC_KEY_TYPE_WEP40;
  337                 break;
  338         case WLAN_CIPHER_SUITE_WEP104:
  339                 hw_key_type = RTW89_SEC_KEY_TYPE_WEP104;
  340                 break;
  341         case WLAN_CIPHER_SUITE_CCMP:
  342                 hw_key_type = RTW89_SEC_KEY_TYPE_CCMP128;
  343                 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
  344                 break;
  345         case WLAN_CIPHER_SUITE_CCMP_256:
  346                 hw_key_type = RTW89_SEC_KEY_TYPE_CCMP256;
  347                 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
  348                 ext_key = true;
  349                 break;
  350         case WLAN_CIPHER_SUITE_GCMP:
  351                 hw_key_type = RTW89_SEC_KEY_TYPE_GCMP128;
  352                 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
  353                 break;
  354         case WLAN_CIPHER_SUITE_GCMP_256:
  355                 hw_key_type = RTW89_SEC_KEY_TYPE_GCMP256;
  356                 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
  357                 ext_key = true;
  358                 break;
  359         default:
  360                 return -EOPNOTSUPP;
  361         }
  362 
  363         if (!chip->hw_sec_hdr)
  364                 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
  365 
  366         ret = rtw89_cam_sec_key_install(rtwdev, vif, sta, key, hw_key_type,
  367                                         ext_key);
  368         if (ret) {
  369                 rtw89_err(rtwdev, "failed to install key type %d ext %d: %d\n",
  370                           hw_key_type, ext_key, ret);
  371                 return ret;
  372         }
  373 
  374         return 0;
  375 }
  376 
  377 int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
  378                           struct ieee80211_vif *vif,
  379                           struct ieee80211_sta *sta,
  380                           struct ieee80211_key_conf *key,
  381                           bool inform_fw)
  382 {
  383         struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
  384         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  385         struct rtw89_vif *rtwvif;
  386         struct rtw89_addr_cam_entry *addr_cam;
  387         struct rtw89_sec_cam_entry *sec_cam;
  388         u8 key_idx = key->hw_key_idx;
  389         u8 sec_cam_idx;
  390         int ret = 0;
  391 
  392         if (!vif) {
  393                 rtw89_err(rtwdev, "No iface for deleting sec cam\n");
  394                 return -EINVAL;
  395         }
  396 
  397         rtwvif = (struct rtw89_vif *)vif->drv_priv;
  398         addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
  399         sec_cam = addr_cam->sec_entries[key_idx];
  400         if (!sec_cam)
  401                 return -EINVAL;
  402 
  403         /* detach sec cam from addr cam */
  404         clear_bit(key_idx, addr_cam->sec_cam_map);
  405         addr_cam->sec_entries[key_idx] = NULL;
  406         if (inform_fw) {
  407                 ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
  408                 if (ret)
  409                         rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret);
  410                 ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
  411                 if (ret)
  412                         rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret);
  413         }
  414 
  415         /* clear valid bit in addr cam will disable sec cam,
  416          * so we don't need to send H2C command again
  417          */
  418         sec_cam_idx = sec_cam->sec_cam_idx;
  419         clear_bit(sec_cam_idx, cam_info->sec_cam_map);
  420         if (sec_cam->ext_key)
  421                 clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map);
  422 
  423         kfree(sec_cam);
  424 
  425         return ret;
  426 }
  427 
  428 static void rtw89_cam_reset_key_iter(struct ieee80211_hw *hw,
  429                                      struct ieee80211_vif *vif,
  430                                      struct ieee80211_sta *sta,
  431                                      struct ieee80211_key_conf *key,
  432                                      void *data)
  433 {
  434         struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
  435 
  436         rtw89_cam_sec_key_del(rtwdev, vif, sta, key, false);
  437 }
  438 
  439 void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev,
  440                                struct rtw89_addr_cam_entry *addr_cam)
  441 {
  442         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  443 
  444         addr_cam->valid = false;
  445         clear_bit(addr_cam->addr_cam_idx, cam_info->addr_cam_map);
  446 }
  447 
  448 void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev,
  449                                 struct rtw89_bssid_cam_entry *bssid_cam)
  450 {
  451         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  452 
  453         bssid_cam->valid = false;
  454         clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map);
  455 }
  456 
  457 void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
  458 {
  459         struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
  460         struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
  461 
  462         rtw89_cam_deinit_addr_cam(rtwdev, addr_cam);
  463         rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam);
  464 }
  465 
  466 void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev)
  467 {
  468         rcu_read_lock();
  469         ieee80211_iter_keys_rcu(rtwdev->hw, NULL, rtw89_cam_reset_key_iter, rtwdev);
  470         rcu_read_unlock();
  471 }
  472 
  473 static int rtw89_cam_get_avail_addr_cam(struct rtw89_dev *rtwdev,
  474                                         u8 *addr_cam_idx)
  475 {
  476         const struct rtw89_chip_info *chip = rtwdev->chip;
  477         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  478         u8 addr_cam_num = chip->acam_num;
  479         u8 idx;
  480 
  481         idx = find_first_zero_bit(cam_info->addr_cam_map, addr_cam_num);
  482         if (idx >= addr_cam_num)
  483                 return -EBUSY;
  484 
  485         set_bit(idx, cam_info->addr_cam_map);
  486         *addr_cam_idx = idx;
  487 
  488         return 0;
  489 }
  490 
  491 int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev,
  492                             struct rtw89_addr_cam_entry *addr_cam,
  493                             const struct rtw89_bssid_cam_entry *bssid_cam)
  494 {
  495         u8 addr_cam_idx;
  496         int i;
  497         int ret;
  498 
  499         if (unlikely(addr_cam->valid)) {
  500                 rtw89_debug(rtwdev, RTW89_DBG_FW,
  501                             "addr cam is already valid; skip init\n");
  502                 return 0;
  503         }
  504 
  505         ret = rtw89_cam_get_avail_addr_cam(rtwdev, &addr_cam_idx);
  506         if (ret) {
  507                 rtw89_err(rtwdev, "failed to get available addr cam\n");
  508                 return ret;
  509         }
  510 
  511         addr_cam->addr_cam_idx = addr_cam_idx;
  512         addr_cam->len = ADDR_CAM_ENT_SIZE;
  513         addr_cam->offset = 0;
  514         addr_cam->valid = true;
  515         addr_cam->addr_mask = 0;
  516         addr_cam->mask_sel = RTW89_NO_MSK;
  517         addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL;
  518         bitmap_zero(addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM);
  519 
  520         for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) {
  521                 addr_cam->sec_ent_keyid[i] = 0;
  522                 addr_cam->sec_ent[i] = 0;
  523         }
  524 
  525         /* associate addr cam with bssid cam */
  526         addr_cam->bssid_cam_idx = bssid_cam->bssid_cam_idx;
  527 
  528         return 0;
  529 }
  530 
  531 static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev,
  532                                          u8 *bssid_cam_idx)
  533 {
  534         const struct rtw89_chip_info *chip = rtwdev->chip;
  535         struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
  536         u8 bssid_cam_num = chip->bcam_num;
  537         u8 idx;
  538 
  539         idx = find_first_zero_bit(cam_info->bssid_cam_map, bssid_cam_num);
  540         if (idx >= bssid_cam_num)
  541                 return -EBUSY;
  542 
  543         set_bit(idx, cam_info->bssid_cam_map);
  544         *bssid_cam_idx = idx;
  545 
  546         return 0;
  547 }
  548 
  549 int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev,
  550                              struct rtw89_vif *rtwvif,
  551                              struct rtw89_bssid_cam_entry *bssid_cam,
  552                              const u8 *bssid)
  553 {
  554         u8 bssid_cam_idx;
  555         int ret;
  556 
  557         if (unlikely(bssid_cam->valid)) {
  558                 rtw89_debug(rtwdev, RTW89_DBG_FW,
  559                             "bssid cam is already valid; skip init\n");
  560                 return 0;
  561         }
  562 
  563         ret = rtw89_cam_get_avail_bssid_cam(rtwdev, &bssid_cam_idx);
  564         if (ret) {
  565                 rtw89_err(rtwdev, "failed to get available bssid cam\n");
  566                 return ret;
  567         }
  568 
  569         bssid_cam->bssid_cam_idx = bssid_cam_idx;
  570         bssid_cam->phy_idx = rtwvif->phy_idx;
  571         bssid_cam->len = BSSID_CAM_ENT_SIZE;
  572         bssid_cam->offset = 0;
  573         bssid_cam->valid = true;
  574         ether_addr_copy(bssid_cam->bssid, bssid);
  575 
  576         return 0;
  577 }
  578 
  579 void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
  580 {
  581         struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
  582 
  583         ether_addr_copy(bssid_cam->bssid, rtwvif->bssid);
  584 }
  585 
  586 int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
  587 {
  588         struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam;
  589         struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam;
  590         int ret;
  591 
  592         ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid);
  593         if (ret) {
  594                 rtw89_err(rtwdev, "failed to init bssid cam\n");
  595                 return ret;
  596         }
  597 
  598         ret = rtw89_cam_init_addr_cam(rtwdev, addr_cam, bssid_cam);
  599         if (ret) {
  600                 rtw89_err(rtwdev, "failed to init addr cam\n");
  601                 return ret;
  602         }
  603 
  604         return 0;
  605 }
  606 
  607 int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev,
  608                                   struct rtw89_vif *rtwvif,
  609                                   struct rtw89_sta *rtwsta, u8 *cmd)
  610 {
  611         struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
  612         struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta);
  613         u8 bss_color = vif->bss_conf.he_bss_color.color;
  614         u8 bss_mask;
  615 
  616         if (vif->bss_conf.nontransmitted)
  617                 bss_mask = RTW89_BSSID_MATCH_5_BYTES;
  618         else
  619                 bss_mask = RTW89_BSSID_MATCH_ALL;
  620 
  621         FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx);
  622         FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset);
  623         FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len);
  624         FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid);
  625         FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask);
  626         FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx);
  627         FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color);
  628 
  629         FWCMD_SET_ADDR_BSSID_BSSID0(cmd, bssid_cam->bssid[0]);
  630         FWCMD_SET_ADDR_BSSID_BSSID1(cmd, bssid_cam->bssid[1]);
  631         FWCMD_SET_ADDR_BSSID_BSSID2(cmd, bssid_cam->bssid[2]);
  632         FWCMD_SET_ADDR_BSSID_BSSID3(cmd, bssid_cam->bssid[3]);
  633         FWCMD_SET_ADDR_BSSID_BSSID4(cmd, bssid_cam->bssid[4]);
  634         FWCMD_SET_ADDR_BSSID_BSSID5(cmd, bssid_cam->bssid[5]);
  635 
  636         return 0;
  637 }
  638 
  639 static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr)
  640 {
  641         u8 hash = 0;
  642         u8 i;
  643 
  644         for (i = start; i < ETH_ALEN; i++)
  645                 hash ^= addr[i];
  646 
  647         return hash;
  648 }
  649 
  650 void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev,
  651                                   struct rtw89_vif *rtwvif,
  652                                   struct rtw89_sta *rtwsta,
  653                                   const u8 *scan_mac_addr,
  654                                   u8 *cmd)
  655 {
  656         struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
  657         struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
  658         struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
  659         const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr;
  660         u8 sma_hash, tma_hash, addr_msk_start;
  661         u8 sma_start = 0;
  662         u8 tma_start = 0;
  663         u8 *tma = sta ? sta->addr : rtwvif->bssid;
  664 
  665         if (addr_cam->addr_mask != 0) {
  666                 addr_msk_start = __ffs(addr_cam->addr_mask);
  667                 if (addr_cam->mask_sel == RTW89_SMA)
  668                         sma_start = addr_msk_start;
  669                 else if (addr_cam->mask_sel == RTW89_TMA)
  670                         tma_start = addr_msk_start;
  671         }
  672         sma_hash = rtw89_cam_addr_hash(sma_start, sma);
  673         tma_hash = rtw89_cam_addr_hash(tma_start, tma);
  674 
  675         FWCMD_SET_ADDR_IDX(cmd, addr_cam->addr_cam_idx);
  676         FWCMD_SET_ADDR_OFFSET(cmd, addr_cam->offset);
  677         FWCMD_SET_ADDR_LEN(cmd, addr_cam->len);
  678 
  679         FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid);
  680         FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type);
  681         FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond);
  682         FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule);
  683         FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx);
  684         FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask);
  685         FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel);
  686         FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash);
  687         FWCMD_SET_ADDR_TMA_HASH(cmd, tma_hash);
  688 
  689         FWCMD_SET_ADDR_BSSID_CAM_IDX(cmd, addr_cam->bssid_cam_idx);
  690 
  691         FWCMD_SET_ADDR_SMA0(cmd, sma[0]);
  692         FWCMD_SET_ADDR_SMA1(cmd, sma[1]);
  693         FWCMD_SET_ADDR_SMA2(cmd, sma[2]);
  694         FWCMD_SET_ADDR_SMA3(cmd, sma[3]);
  695         FWCMD_SET_ADDR_SMA4(cmd, sma[4]);
  696         FWCMD_SET_ADDR_SMA5(cmd, sma[5]);
  697 
  698         FWCMD_SET_ADDR_TMA0(cmd, tma[0]);
  699         FWCMD_SET_ADDR_TMA1(cmd, tma[1]);
  700         FWCMD_SET_ADDR_TMA2(cmd, tma[2]);
  701         FWCMD_SET_ADDR_TMA3(cmd, tma[3]);
  702         FWCMD_SET_ADDR_TMA4(cmd, tma[4]);
  703         FWCMD_SET_ADDR_TMA5(cmd, tma[5]);
  704 
  705         FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port);
  706         FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port);
  707         FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger);
  708         FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop);
  709         FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind);
  710         FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind);
  711         FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
  712         if (rtwvif->net_type == RTW89_NET_TYPE_INFRA)
  713                 FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff);
  714         else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
  715                 FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0);
  716         FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern);
  717         FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc);
  718         FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic);
  719         FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi);
  720         FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode);
  721         FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]);
  722         FWCMD_SET_ADDR_SEC_ENT1_KEYID(cmd, addr_cam->sec_ent_keyid[1]);
  723         FWCMD_SET_ADDR_SEC_ENT2_KEYID(cmd, addr_cam->sec_ent_keyid[2]);
  724         FWCMD_SET_ADDR_SEC_ENT3_KEYID(cmd, addr_cam->sec_ent_keyid[3]);
  725         FWCMD_SET_ADDR_SEC_ENT4_KEYID(cmd, addr_cam->sec_ent_keyid[4]);
  726         FWCMD_SET_ADDR_SEC_ENT5_KEYID(cmd, addr_cam->sec_ent_keyid[5]);
  727         FWCMD_SET_ADDR_SEC_ENT6_KEYID(cmd, addr_cam->sec_ent_keyid[6]);
  728 
  729         FWCMD_SET_ADDR_SEC_ENT_VALID(cmd, addr_cam->sec_cam_map[0] & 0xff);
  730         FWCMD_SET_ADDR_SEC_ENT0(cmd, addr_cam->sec_ent[0]);
  731         FWCMD_SET_ADDR_SEC_ENT1(cmd, addr_cam->sec_ent[1]);
  732         FWCMD_SET_ADDR_SEC_ENT2(cmd, addr_cam->sec_ent[2]);
  733         FWCMD_SET_ADDR_SEC_ENT3(cmd, addr_cam->sec_ent[3]);
  734         FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]);
  735         FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]);
  736         FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]);
  737 }
  738 
  739 void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev,
  740                                          struct rtw89_vif *rtwvif,
  741                                          struct rtw89_sta *rtwsta,
  742                                          u8 *cmd)
  743 {
  744         struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta);
  745 
  746         SET_DCTL_MACID_V1(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id);
  747         SET_DCTL_OPERATION_V1(cmd, 1);
  748 
  749         SET_DCTL_SEC_ENT0_KEYID_V1(cmd, addr_cam->sec_ent_keyid[0]);
  750         SET_DCTL_SEC_ENT1_KEYID_V1(cmd, addr_cam->sec_ent_keyid[1]);
  751         SET_DCTL_SEC_ENT2_KEYID_V1(cmd, addr_cam->sec_ent_keyid[2]);
  752         SET_DCTL_SEC_ENT3_KEYID_V1(cmd, addr_cam->sec_ent_keyid[3]);
  753         SET_DCTL_SEC_ENT4_KEYID_V1(cmd, addr_cam->sec_ent_keyid[4]);
  754         SET_DCTL_SEC_ENT5_KEYID_V1(cmd, addr_cam->sec_ent_keyid[5]);
  755         SET_DCTL_SEC_ENT6_KEYID_V1(cmd, addr_cam->sec_ent_keyid[6]);
  756 
  757         SET_DCTL_SEC_ENT_VALID_V1(cmd, addr_cam->sec_cam_map[0] & 0xff);
  758         SET_DCTL_SEC_ENT0_V1(cmd, addr_cam->sec_ent[0]);
  759         SET_DCTL_SEC_ENT1_V1(cmd, addr_cam->sec_ent[1]);
  760         SET_DCTL_SEC_ENT2_V1(cmd, addr_cam->sec_ent[2]);
  761         SET_DCTL_SEC_ENT3_V1(cmd, addr_cam->sec_ent[3]);
  762         SET_DCTL_SEC_ENT4_V1(cmd, addr_cam->sec_ent[4]);
  763         SET_DCTL_SEC_ENT5_V1(cmd, addr_cam->sec_ent[5]);
  764         SET_DCTL_SEC_ENT6_V1(cmd, addr_cam->sec_ent[6]);
  765 }

Cache object: 98ec6c7d661ea5bdd2448ea3c4d9f0ba


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.