root/drivers/net/wireless/realtek/rtw88/mac80211.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_ops_tx
  2. rtw_ops_start
  3. rtw_ops_stop
  4. rtw_ops_config
  5. rtw_ops_add_interface
  6. rtw_ops_remove_interface
  7. rtw_ops_configure_filter
  8. rtw_ops_bss_info_changed
  9. rtw_acquire_macid
  10. rtw_release_macid
  11. rtw_ops_sta_add
  12. rtw_ops_sta_remove
  13. rtw_ops_set_key
  14. rtw_ops_ampdu_action
  15. rtw_ops_sw_scan_start
  16. rtw_ops_sw_scan_complete
  17. rtw_ops_mgd_prepare_tx

   1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2 /* Copyright(c) 2018-2019  Realtek Corporation
   3  */
   4 
   5 #include "main.h"
   6 #include "sec.h"
   7 #include "tx.h"
   8 #include "fw.h"
   9 #include "mac.h"
  10 #include "coex.h"
  11 #include "ps.h"
  12 #include "reg.h"
  13 #include "debug.h"
  14 
  15 static void rtw_ops_tx(struct ieee80211_hw *hw,
  16                        struct ieee80211_tx_control *control,
  17                        struct sk_buff *skb)
  18 {
  19         struct rtw_dev *rtwdev = hw->priv;
  20         struct rtw_tx_pkt_info pkt_info = {0};
  21 
  22         if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
  23                 goto out;
  24 
  25         rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
  26         if (rtw_hci_tx(rtwdev, &pkt_info, skb))
  27                 goto out;
  28 
  29         return;
  30 
  31 out:
  32         ieee80211_free_txskb(hw, skb);
  33 }
  34 
  35 static int rtw_ops_start(struct ieee80211_hw *hw)
  36 {
  37         struct rtw_dev *rtwdev = hw->priv;
  38         int ret;
  39 
  40         mutex_lock(&rtwdev->mutex);
  41         ret = rtw_core_start(rtwdev);
  42         mutex_unlock(&rtwdev->mutex);
  43 
  44         return ret;
  45 }
  46 
  47 static void rtw_ops_stop(struct ieee80211_hw *hw)
  48 {
  49         struct rtw_dev *rtwdev = hw->priv;
  50 
  51         mutex_lock(&rtwdev->mutex);
  52         rtw_core_stop(rtwdev);
  53         mutex_unlock(&rtwdev->mutex);
  54 }
  55 
  56 static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
  57 {
  58         struct rtw_dev *rtwdev = hw->priv;
  59         int ret = 0;
  60 
  61         mutex_lock(&rtwdev->mutex);
  62 
  63         if (changed & IEEE80211_CONF_CHANGE_IDLE) {
  64                 if (hw->conf.flags & IEEE80211_CONF_IDLE) {
  65                         rtw_enter_ips(rtwdev);
  66                 } else {
  67                         ret = rtw_leave_ips(rtwdev);
  68                         if (ret) {
  69                                 rtw_err(rtwdev, "failed to leave idle state\n");
  70                                 goto out;
  71                         }
  72                 }
  73         }
  74 
  75         if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
  76                 rtw_set_channel(rtwdev);
  77 
  78 out:
  79         mutex_unlock(&rtwdev->mutex);
  80         return ret;
  81 }
  82 
  83 static const struct rtw_vif_port rtw_vif_port[] = {
  84         [0] = {
  85                 .mac_addr       = {.addr = 0x0610},
  86                 .bssid          = {.addr = 0x0618},
  87                 .net_type       = {.addr = 0x0100, .mask = 0x30000},
  88                 .aid            = {.addr = 0x06a8, .mask = 0x7ff},
  89                 .bcn_ctrl       = {.addr = 0x0550, .mask = 0xff},
  90         },
  91         [1] = {
  92                 .mac_addr       = {.addr = 0x0700},
  93                 .bssid          = {.addr = 0x0708},
  94                 .net_type       = {.addr = 0x0100, .mask = 0xc0000},
  95                 .aid            = {.addr = 0x0710, .mask = 0x7ff},
  96                 .bcn_ctrl       = {.addr = 0x0551, .mask = 0xff},
  97         },
  98         [2] = {
  99                 .mac_addr       = {.addr = 0x1620},
 100                 .bssid          = {.addr = 0x1628},
 101                 .net_type       = {.addr = 0x1100, .mask = 0x3},
 102                 .aid            = {.addr = 0x1600, .mask = 0x7ff},
 103                 .bcn_ctrl       = {.addr = 0x0578, .mask = 0xff},
 104         },
 105         [3] = {
 106                 .mac_addr       = {.addr = 0x1630},
 107                 .bssid          = {.addr = 0x1638},
 108                 .net_type       = {.addr = 0x1100, .mask = 0xc},
 109                 .aid            = {.addr = 0x1604, .mask = 0x7ff},
 110                 .bcn_ctrl       = {.addr = 0x0579, .mask = 0xff},
 111         },
 112         [4] = {
 113                 .mac_addr       = {.addr = 0x1640},
 114                 .bssid          = {.addr = 0x1648},
 115                 .net_type       = {.addr = 0x1100, .mask = 0x30},
 116                 .aid            = {.addr = 0x1608, .mask = 0x7ff},
 117                 .bcn_ctrl       = {.addr = 0x057a, .mask = 0xff},
 118         },
 119 };
 120 
 121 static int rtw_ops_add_interface(struct ieee80211_hw *hw,
 122                                  struct ieee80211_vif *vif)
 123 {
 124         struct rtw_dev *rtwdev = hw->priv;
 125         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 126         enum rtw_net_type net_type;
 127         u32 config = 0;
 128         u8 port = 0;
 129         u8 bcn_ctrl = 0;
 130 
 131         rtwvif->port = port;
 132         rtwvif->vif = vif;
 133         rtwvif->stats.tx_unicast = 0;
 134         rtwvif->stats.rx_unicast = 0;
 135         rtwvif->stats.tx_cnt = 0;
 136         rtwvif->stats.rx_cnt = 0;
 137         rtwvif->in_lps = false;
 138         rtwvif->conf = &rtw_vif_port[port];
 139 
 140         mutex_lock(&rtwdev->mutex);
 141 
 142         switch (vif->type) {
 143         case NL80211_IFTYPE_AP:
 144         case NL80211_IFTYPE_MESH_POINT:
 145                 net_type = RTW_NET_AP_MODE;
 146                 bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
 147                 break;
 148         case NL80211_IFTYPE_ADHOC:
 149                 net_type = RTW_NET_AD_HOC;
 150                 bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
 151                 break;
 152         case NL80211_IFTYPE_STATION:
 153         default:
 154                 net_type = RTW_NET_NO_LINK;
 155                 bcn_ctrl = BIT_EN_BCN_FUNCTION;
 156                 break;
 157         }
 158 
 159         ether_addr_copy(rtwvif->mac_addr, vif->addr);
 160         config |= PORT_SET_MAC_ADDR;
 161         rtwvif->net_type = net_type;
 162         config |= PORT_SET_NET_TYPE;
 163         rtwvif->bcn_ctrl = bcn_ctrl;
 164         config |= PORT_SET_BCN_CTRL;
 165         rtw_vif_port_config(rtwdev, rtwvif, config);
 166 
 167         mutex_unlock(&rtwdev->mutex);
 168 
 169         rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
 170         return 0;
 171 }
 172 
 173 static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
 174                                      struct ieee80211_vif *vif)
 175 {
 176         struct rtw_dev *rtwdev = hw->priv;
 177         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 178         u32 config = 0;
 179 
 180         rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
 181 
 182         mutex_lock(&rtwdev->mutex);
 183 
 184         eth_zero_addr(rtwvif->mac_addr);
 185         config |= PORT_SET_MAC_ADDR;
 186         rtwvif->net_type = RTW_NET_NO_LINK;
 187         config |= PORT_SET_NET_TYPE;
 188         rtwvif->bcn_ctrl = 0;
 189         config |= PORT_SET_BCN_CTRL;
 190         rtw_vif_port_config(rtwdev, rtwvif, config);
 191 
 192         mutex_unlock(&rtwdev->mutex);
 193 }
 194 
 195 static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
 196                                      unsigned int changed_flags,
 197                                      unsigned int *new_flags,
 198                                      u64 multicast)
 199 {
 200         struct rtw_dev *rtwdev = hw->priv;
 201 
 202         *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
 203                       FIF_BCN_PRBRESP_PROMISC;
 204 
 205         mutex_lock(&rtwdev->mutex);
 206 
 207         if (changed_flags & FIF_ALLMULTI) {
 208                 if (*new_flags & FIF_ALLMULTI)
 209                         rtwdev->hal.rcr |= BIT_AM | BIT_AB;
 210                 else
 211                         rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
 212         }
 213         if (changed_flags & FIF_FCSFAIL) {
 214                 if (*new_flags & FIF_FCSFAIL)
 215                         rtwdev->hal.rcr |= BIT_ACRC32;
 216                 else
 217                         rtwdev->hal.rcr &= ~(BIT_ACRC32);
 218         }
 219         if (changed_flags & FIF_OTHER_BSS) {
 220                 if (*new_flags & FIF_OTHER_BSS)
 221                         rtwdev->hal.rcr |= BIT_AAP;
 222                 else
 223                         rtwdev->hal.rcr &= ~(BIT_AAP);
 224         }
 225         if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 226                 if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
 227                         rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA);
 228                 else
 229                         rtwdev->hal.rcr |= BIT_CBSSID_BCN;
 230         }
 231 
 232         rtw_dbg(rtwdev, RTW_DBG_RX,
 233                 "config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n",
 234                 changed_flags, *new_flags, rtwdev->hal.rcr);
 235 
 236         rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
 237 
 238         mutex_unlock(&rtwdev->mutex);
 239 }
 240 
 241 static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
 242                                      struct ieee80211_vif *vif,
 243                                      struct ieee80211_bss_conf *conf,
 244                                      u32 changed)
 245 {
 246         struct rtw_dev *rtwdev = hw->priv;
 247         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 248         u32 config = 0;
 249 
 250         mutex_lock(&rtwdev->mutex);
 251 
 252         if (changed & BSS_CHANGED_ASSOC) {
 253                 struct rtw_chip_info *chip = rtwdev->chip;
 254                 enum rtw_net_type net_type;
 255 
 256                 if (conf->assoc) {
 257                         rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
 258                         net_type = RTW_NET_MGD_LINKED;
 259                         chip->ops->phy_calibration(rtwdev);
 260 
 261                         rtwvif->aid = conf->aid;
 262                         rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true);
 263                         rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true);
 264                         rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
 265                         rtw_fw_download_rsvd_page(rtwdev, vif);
 266                         rtw_send_rsvd_page_h2c(rtwdev);
 267                         rtw_coex_media_status_notify(rtwdev, conf->assoc);
 268                 } else {
 269                         net_type = RTW_NET_NO_LINK;
 270                         rtwvif->aid = 0;
 271                         rtw_reset_rsvd_page(rtwdev);
 272                 }
 273 
 274                 rtwvif->net_type = net_type;
 275                 config |= PORT_SET_NET_TYPE;
 276                 config |= PORT_SET_AID;
 277         }
 278 
 279         if (changed & BSS_CHANGED_BSSID) {
 280                 ether_addr_copy(rtwvif->bssid, conf->bssid);
 281                 config |= PORT_SET_BSSID;
 282         }
 283 
 284         if (changed & BSS_CHANGED_BEACON)
 285                 rtw_fw_download_rsvd_page(rtwdev, vif);
 286 
 287         rtw_vif_port_config(rtwdev, rtwvif, config);
 288 
 289         mutex_unlock(&rtwdev->mutex);
 290 }
 291 
 292 static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
 293 {
 294         unsigned long mac_id;
 295 
 296         mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
 297         if (mac_id < RTW_MAX_MAC_ID_NUM)
 298                 set_bit(mac_id, rtwdev->mac_id_map);
 299 
 300         return mac_id;
 301 }
 302 
 303 static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
 304 {
 305         clear_bit(mac_id, rtwdev->mac_id_map);
 306 }
 307 
 308 static int rtw_ops_sta_add(struct ieee80211_hw *hw,
 309                            struct ieee80211_vif *vif,
 310                            struct ieee80211_sta *sta)
 311 {
 312         struct rtw_dev *rtwdev = hw->priv;
 313         struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
 314         int ret = 0;
 315 
 316         mutex_lock(&rtwdev->mutex);
 317 
 318         si->mac_id = rtw_acquire_macid(rtwdev);
 319         if (si->mac_id >= RTW_MAX_MAC_ID_NUM) {
 320                 ret = -ENOSPC;
 321                 goto out;
 322         }
 323 
 324         si->sta = sta;
 325         si->vif = vif;
 326         si->init_ra_lv = 1;
 327         ewma_rssi_init(&si->avg_rssi);
 328 
 329         rtw_update_sta_info(rtwdev, si);
 330         rtw_fw_media_status_report(rtwdev, si->mac_id, true);
 331 
 332         rtwdev->sta_cnt++;
 333 
 334         rtw_info(rtwdev, "sta %pM joined with macid %d\n",
 335                  sta->addr, si->mac_id);
 336 
 337 out:
 338         mutex_unlock(&rtwdev->mutex);
 339         return ret;
 340 }
 341 
 342 static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
 343                               struct ieee80211_vif *vif,
 344                               struct ieee80211_sta *sta)
 345 {
 346         struct rtw_dev *rtwdev = hw->priv;
 347         struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
 348 
 349         mutex_lock(&rtwdev->mutex);
 350 
 351         rtw_release_macid(rtwdev, si->mac_id);
 352         rtw_fw_media_status_report(rtwdev, si->mac_id, false);
 353 
 354         rtwdev->sta_cnt--;
 355 
 356         rtw_info(rtwdev, "sta %pM with macid %d left\n",
 357                  sta->addr, si->mac_id);
 358 
 359         mutex_unlock(&rtwdev->mutex);
 360         return 0;
 361 }
 362 
 363 static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 364                            struct ieee80211_vif *vif, struct ieee80211_sta *sta,
 365                            struct ieee80211_key_conf *key)
 366 {
 367         struct rtw_dev *rtwdev = hw->priv;
 368         struct rtw_sec_desc *sec = &rtwdev->sec;
 369         u8 hw_key_type;
 370         u8 hw_key_idx;
 371         int ret = 0;
 372 
 373         switch (key->cipher) {
 374         case WLAN_CIPHER_SUITE_WEP40:
 375                 hw_key_type = RTW_CAM_WEP40;
 376                 break;
 377         case WLAN_CIPHER_SUITE_WEP104:
 378                 hw_key_type = RTW_CAM_WEP104;
 379                 break;
 380         case WLAN_CIPHER_SUITE_TKIP:
 381                 hw_key_type = RTW_CAM_TKIP;
 382                 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
 383                 break;
 384         case WLAN_CIPHER_SUITE_CCMP:
 385                 hw_key_type = RTW_CAM_AES;
 386                 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
 387                 break;
 388         case WLAN_CIPHER_SUITE_AES_CMAC:
 389         case WLAN_CIPHER_SUITE_BIP_CMAC_256:
 390         case WLAN_CIPHER_SUITE_BIP_GMAC_128:
 391         case WLAN_CIPHER_SUITE_BIP_GMAC_256:
 392                 /* suppress error messages */
 393                 return -EOPNOTSUPP;
 394         default:
 395                 return -ENOTSUPP;
 396         }
 397 
 398         mutex_lock(&rtwdev->mutex);
 399 
 400         if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
 401                 hw_key_idx = rtw_sec_get_free_cam(sec);
 402         } else {
 403                 /* multiple interfaces? */
 404                 hw_key_idx = key->keyidx;
 405         }
 406 
 407         if (hw_key_idx > sec->total_cam_num) {
 408                 ret = -ENOSPC;
 409                 goto out;
 410         }
 411 
 412         switch (cmd) {
 413         case SET_KEY:
 414                 /* need sw generated IV */
 415                 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 416                 key->hw_key_idx = hw_key_idx;
 417                 rtw_sec_write_cam(rtwdev, sec, sta, key,
 418                                   hw_key_type, hw_key_idx);
 419                 break;
 420         case DISABLE_KEY:
 421                 rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
 422                 break;
 423         }
 424 
 425 out:
 426         mutex_unlock(&rtwdev->mutex);
 427 
 428         return ret;
 429 }
 430 
 431 static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
 432                                 struct ieee80211_vif *vif,
 433                                 struct ieee80211_ampdu_params *params)
 434 {
 435         struct ieee80211_sta *sta = params->sta;
 436         u16 tid = params->tid;
 437 
 438         switch (params->action) {
 439         case IEEE80211_AMPDU_TX_START:
 440                 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 441                 break;
 442         case IEEE80211_AMPDU_TX_STOP_CONT:
 443         case IEEE80211_AMPDU_TX_STOP_FLUSH:
 444         case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 445                 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 446                 break;
 447         case IEEE80211_AMPDU_TX_OPERATIONAL:
 448         case IEEE80211_AMPDU_RX_START:
 449         case IEEE80211_AMPDU_RX_STOP:
 450                 break;
 451         default:
 452                 WARN_ON(1);
 453                 return -ENOTSUPP;
 454         }
 455 
 456         return 0;
 457 }
 458 
 459 static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
 460                                   struct ieee80211_vif *vif,
 461                                   const u8 *mac_addr)
 462 {
 463         struct rtw_dev *rtwdev = hw->priv;
 464         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 465         u32 config = 0;
 466 
 467         rtw_leave_lps(rtwdev, rtwvif);
 468 
 469         mutex_lock(&rtwdev->mutex);
 470 
 471         ether_addr_copy(rtwvif->mac_addr, mac_addr);
 472         config |= PORT_SET_MAC_ADDR;
 473         rtw_vif_port_config(rtwdev, rtwvif, config);
 474 
 475         rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
 476 
 477         rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE);
 478         rtw_flag_set(rtwdev, RTW_FLAG_SCANNING);
 479 
 480         mutex_unlock(&rtwdev->mutex);
 481 }
 482 
 483 static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
 484                                      struct ieee80211_vif *vif)
 485 {
 486         struct rtw_dev *rtwdev = hw->priv;
 487         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 488         u32 config = 0;
 489 
 490         mutex_lock(&rtwdev->mutex);
 491 
 492         rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING);
 493         rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE);
 494 
 495         ether_addr_copy(rtwvif->mac_addr, vif->addr);
 496         config |= PORT_SET_MAC_ADDR;
 497         rtw_vif_port_config(rtwdev, rtwvif, config);
 498 
 499         rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
 500 
 501         mutex_unlock(&rtwdev->mutex);
 502 }
 503 
 504 static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
 505                                    struct ieee80211_vif *vif,
 506                                    u16 duration)
 507 {
 508         struct rtw_dev *rtwdev = hw->priv;
 509 
 510         mutex_lock(&rtwdev->mutex);
 511         rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
 512         mutex_unlock(&rtwdev->mutex);
 513 }
 514 
 515 const struct ieee80211_ops rtw_ops = {
 516         .tx                     = rtw_ops_tx,
 517         .start                  = rtw_ops_start,
 518         .stop                   = rtw_ops_stop,
 519         .config                 = rtw_ops_config,
 520         .add_interface          = rtw_ops_add_interface,
 521         .remove_interface       = rtw_ops_remove_interface,
 522         .configure_filter       = rtw_ops_configure_filter,
 523         .bss_info_changed       = rtw_ops_bss_info_changed,
 524         .sta_add                = rtw_ops_sta_add,
 525         .sta_remove             = rtw_ops_sta_remove,
 526         .set_key                = rtw_ops_set_key,
 527         .ampdu_action           = rtw_ops_ampdu_action,
 528         .sw_scan_start          = rtw_ops_sw_scan_start,
 529         .sw_scan_complete       = rtw_ops_sw_scan_complete,
 530         .mgd_prepare_tx         = rtw_ops_mgd_prepare_tx,
 531 };
 532 EXPORT_SYMBOL(rtw_ops);

/* [<][>][^][v][top][bottom][index][help] */