0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/etherdevice.h>
0009 #include <net/mac80211.h>
0010
0011 #include "sta.h"
0012 #include "wfx.h"
0013 #include "fwio.h"
0014 #include "bh.h"
0015 #include "key.h"
0016 #include "scan.h"
0017 #include "debug.h"
0018 #include "hif_tx.h"
0019 #include "hif_tx_mib.h"
0020
0021 #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
0022
0023 u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
0024 {
0025 int i;
0026 u32 ret = 0;
0027
0028 struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
0029
0030 for (i = 0; i < sband->n_bitrates; i++) {
0031 if (rates & BIT(i)) {
0032 if (i >= sband->n_bitrates)
0033 dev_warn(wdev->dev, "unsupported basic rate\n");
0034 else
0035 ret |= BIT(sband->bitrates[i].hw_value);
0036 }
0037 }
0038 return ret;
0039 }
0040
0041 void wfx_cooling_timeout_work(struct work_struct *work)
0042 {
0043 struct wfx_dev *wdev = container_of(to_delayed_work(work), struct wfx_dev,
0044 cooling_timeout_work);
0045
0046 wdev->chip_frozen = true;
0047 wfx_tx_unlock(wdev);
0048 }
0049
0050 void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd)
0051 {
0052 if (cmd == STA_NOTIFY_AWAKE) {
0053
0054 if (cancel_delayed_work(&wdev->cooling_timeout_work))
0055 wfx_tx_unlock(wdev);
0056 } else {
0057
0058 schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ);
0059 wfx_tx_lock(wdev);
0060 }
0061 }
0062
0063 static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
0064 {
0065 static const struct wfx_hif_ie_table_entry filter_ies[] = {
0066 {
0067 .ie_id = WLAN_EID_VENDOR_SPECIFIC,
0068 .has_changed = 1,
0069 .no_longer = 1,
0070 .has_appeared = 1,
0071 .oui = { 0x50, 0x6F, 0x9A },
0072 }, {
0073 .ie_id = WLAN_EID_HT_OPERATION,
0074 .has_changed = 1,
0075 .no_longer = 1,
0076 .has_appeared = 1,
0077 }, {
0078 .ie_id = WLAN_EID_ERP_INFO,
0079 .has_changed = 1,
0080 .no_longer = 1,
0081 .has_appeared = 1,
0082 }, {
0083 .ie_id = WLAN_EID_CHANNEL_SWITCH,
0084 .has_changed = 1,
0085 .no_longer = 1,
0086 .has_appeared = 1,
0087 }
0088 };
0089
0090 if (!filter_beacon) {
0091 wfx_hif_beacon_filter_control(wvif, 0, 1);
0092 } else {
0093 wfx_hif_set_beacon_filter_table(wvif, ARRAY_SIZE(filter_ies), filter_ies);
0094 wfx_hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
0095 }
0096 }
0097
0098 void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
0099 unsigned int *total_flags, u64 unused)
0100 {
0101 bool filter_bssid, filter_prbreq, filter_beacon;
0102 struct ieee80211_vif *vif = NULL;
0103 struct wfx_dev *wdev = hw->priv;
0104 struct wfx_vif *wvif = NULL;
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
0115 FIF_PROBE_REQ | FIF_PSPOLL;
0116
0117 mutex_lock(&wdev->conf_mutex);
0118 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
0119 mutex_lock(&wvif->scan_lock);
0120
0121
0122
0123
0124 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
0125 filter_beacon = false;
0126 else
0127 filter_beacon = true;
0128 wfx_filter_beacon(wvif, filter_beacon);
0129
0130 if (*total_flags & FIF_OTHER_BSS)
0131 filter_bssid = false;
0132 else
0133 filter_bssid = true;
0134
0135 vif = wvif_to_vif(wvif);
0136
0137 if (*total_flags & FIF_PROBE_REQ && vif->type == NL80211_IFTYPE_AP) {
0138 dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
0139 *total_flags &= ~FIF_PROBE_REQ;
0140 }
0141
0142 if (*total_flags & FIF_PROBE_REQ)
0143 filter_prbreq = false;
0144 else
0145 filter_prbreq = true;
0146 wfx_hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
0147
0148 mutex_unlock(&wvif->scan_lock);
0149 }
0150 mutex_unlock(&wdev->conf_mutex);
0151 }
0152
0153 static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
0154 {
0155 struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
0156 struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
0157 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0158
0159 WARN(!vif->cfg.assoc && enable_ps,
0160 "enable_ps is reliable only if associated");
0161 if (wdev_to_wvif(wvif->wdev, 0)) {
0162 struct wfx_vif *wvif_ch0 = wdev_to_wvif(wvif->wdev, 0);
0163 struct ieee80211_vif *vif_ch0 = wvif_to_vif(wvif_ch0);
0164
0165 chan0 = vif_ch0->bss_conf.chandef.chan;
0166 }
0167 if (wdev_to_wvif(wvif->wdev, 1)) {
0168 struct wfx_vif *wvif_ch1 = wdev_to_wvif(wvif->wdev, 1);
0169 struct ieee80211_vif *vif_ch1 = wvif_to_vif(wvif_ch1);
0170
0171 chan1 = vif_ch1->bss_conf.chandef.chan;
0172 }
0173 if (chan0 && chan1 && vif->type != NL80211_IFTYPE_AP) {
0174 if (chan0->hw_value == chan1->hw_value) {
0175
0176 if (enable_ps)
0177 *enable_ps = false;
0178 if (vif->cfg.assoc && vif->cfg.ps)
0179 dev_info(wvif->wdev->dev, "ignoring requested PS mode");
0180 return -1;
0181 }
0182
0183 if (enable_ps)
0184 *enable_ps = true;
0185 if (wfx_api_older_than(wvif->wdev, 3, 2))
0186 return 0;
0187 else
0188 return 30;
0189 }
0190 if (enable_ps)
0191 *enable_ps = vif->cfg.ps;
0192 if (vif->cfg.assoc && vif->cfg.ps)
0193 return conf->dynamic_ps_timeout;
0194 else
0195 return -1;
0196 }
0197
0198 int wfx_update_pm(struct wfx_vif *wvif)
0199 {
0200 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0201 int ps_timeout;
0202 bool ps;
0203
0204 if (!vif->cfg.assoc)
0205 return 0;
0206 ps_timeout = wfx_get_ps_timeout(wvif, &ps);
0207 if (!ps)
0208 ps_timeout = 0;
0209 WARN_ON(ps_timeout < 0);
0210 if (wvif->uapsd_mask)
0211 ps_timeout = 0;
0212
0213 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, TU_TO_JIFFIES(512)))
0214 dev_warn(wvif->wdev->dev, "timeout while waiting of set_pm_mode_complete\n");
0215 return wfx_hif_set_pm(wvif, ps, ps_timeout);
0216 }
0217
0218 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0219 unsigned int link_id, u16 queue,
0220 const struct ieee80211_tx_queue_params *params)
0221 {
0222 struct wfx_dev *wdev = hw->priv;
0223 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0224 int old_uapsd = wvif->uapsd_mask;
0225
0226 WARN_ON(queue >= hw->queues);
0227
0228 mutex_lock(&wdev->conf_mutex);
0229 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
0230 wfx_hif_set_edca_queue_params(wvif, queue, params);
0231 if (vif->type == NL80211_IFTYPE_STATION &&
0232 old_uapsd != wvif->uapsd_mask) {
0233 wfx_hif_set_uapsd_info(wvif, wvif->uapsd_mask);
0234 wfx_update_pm(wvif);
0235 }
0236 mutex_unlock(&wdev->conf_mutex);
0237 return 0;
0238 }
0239
0240 int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
0241 {
0242 struct wfx_dev *wdev = hw->priv;
0243 struct wfx_vif *wvif = NULL;
0244
0245 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
0246 wfx_hif_rts_threshold(wvif, value);
0247 return 0;
0248 }
0249
0250 void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
0251 {
0252
0253
0254
0255 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0256 int rcpi_rssi;
0257 int cqm_evt;
0258
0259 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
0260 if (rcpi_rssi <= vif->bss_conf.cqm_rssi_thold)
0261 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
0262 else
0263 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
0264 ieee80211_cqm_rssi_notify(vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
0265 }
0266
0267 static void wfx_beacon_loss_work(struct work_struct *work)
0268 {
0269 struct wfx_vif *wvif = container_of(to_delayed_work(work), struct wfx_vif,
0270 beacon_loss_work);
0271 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0272 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
0273
0274 ieee80211_beacon_loss(vif);
0275 schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(bss_conf->beacon_int));
0276 }
0277
0278 void wfx_set_default_unicast_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int idx)
0279 {
0280 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0281
0282 wfx_hif_wep_default_key_id(wvif, idx);
0283 }
0284
0285 void wfx_reset(struct wfx_vif *wvif)
0286 {
0287 struct wfx_dev *wdev = wvif->wdev;
0288
0289 wfx_tx_lock_flush(wdev);
0290 wfx_hif_reset(wvif, false);
0291 wfx_tx_policy_init(wvif);
0292 if (wvif_count(wdev) <= 1)
0293 wfx_hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
0294 wfx_tx_unlock(wdev);
0295 wvif->join_in_progress = false;
0296 cancel_delayed_work_sync(&wvif->beacon_loss_work);
0297 wvif = NULL;
0298 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
0299 wfx_update_pm(wvif);
0300 }
0301
0302 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta)
0303 {
0304 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0305 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
0306
0307 sta_priv->vif_id = wvif->id;
0308
0309 if (vif->type == NL80211_IFTYPE_STATION)
0310 wfx_hif_set_mfp(wvif, sta->mfp, sta->mfp);
0311
0312
0313 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
0314 return 0;
0315 sta_priv->link_id = ffz(wvif->link_id_map);
0316 wvif->link_id_map |= BIT(sta_priv->link_id);
0317 WARN_ON(!sta_priv->link_id);
0318 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
0319 wfx_hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp);
0320
0321 return 0;
0322 }
0323
0324 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta)
0325 {
0326 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0327 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
0328
0329
0330 if (!sta_priv->link_id)
0331 return 0;
0332
0333 wfx_hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false);
0334 wvif->link_id_map &= ~BIT(sta_priv->link_id);
0335 return 0;
0336 }
0337
0338 static int wfx_upload_ap_templates(struct wfx_vif *wvif)
0339 {
0340 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0341 struct sk_buff *skb;
0342
0343 skb = ieee80211_beacon_get(wvif->wdev->hw, vif, 0);
0344 if (!skb)
0345 return -ENOMEM;
0346 wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, API_RATE_INDEX_B_1MBPS);
0347 dev_kfree_skb(skb);
0348
0349 skb = ieee80211_proberesp_get(wvif->wdev->hw, vif);
0350 if (!skb)
0351 return -ENOMEM;
0352 wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, API_RATE_INDEX_B_1MBPS);
0353 dev_kfree_skb(skb);
0354 return 0;
0355 }
0356
0357 static void wfx_set_mfp_ap(struct wfx_vif *wvif)
0358 {
0359 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0360 struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, vif, 0);
0361 const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
0362 const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
0363 skb->len - ieoffset);
0364 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
0365 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
0366 const int akm_suite_size = 4 / sizeof(u16);
0367
0368 if (ptr) {
0369 ptr += pairwise_cipher_suite_count_offset;
0370 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
0371 return;
0372 ptr += 1 + pairwise_cipher_suite_size * *ptr;
0373 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
0374 return;
0375 ptr += 1 + akm_suite_size * *ptr;
0376 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
0377 return;
0378 wfx_hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
0379 }
0380 }
0381
0382 int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0383 struct ieee80211_bss_conf *link_conf)
0384 {
0385 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0386 struct wfx_dev *wdev = wvif->wdev;
0387 int ret;
0388
0389 wvif = NULL;
0390 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
0391 wfx_update_pm(wvif);
0392 wvif = (struct wfx_vif *)vif->drv_priv;
0393 wfx_upload_ap_templates(wvif);
0394 ret = wfx_hif_start(wvif, &vif->bss_conf, wvif->channel);
0395 if (ret > 0)
0396 return -EIO;
0397 wfx_set_mfp_ap(wvif);
0398 return ret;
0399 }
0400
0401 void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0402 struct ieee80211_bss_conf *link_conf)
0403 {
0404 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0405
0406 wfx_reset(wvif);
0407 }
0408
0409 static void wfx_join(struct wfx_vif *wvif)
0410 {
0411 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0412 struct ieee80211_bss_conf *conf = &vif->bss_conf;
0413 struct cfg80211_bss *bss = NULL;
0414 u8 ssid[IEEE80211_MAX_SSID_LEN];
0415 const u8 *ssid_ie = NULL;
0416 int ssid_len = 0;
0417 int ret;
0418
0419 wfx_tx_lock_flush(wvif->wdev);
0420
0421 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel, conf->bssid, NULL, 0,
0422 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
0423 if (!bss && !vif->cfg.ibss_joined) {
0424 wfx_tx_unlock(wvif->wdev);
0425 return;
0426 }
0427
0428 rcu_read_lock();
0429 if (bss)
0430 ssid_ie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
0431 if (ssid_ie) {
0432 ssid_len = ssid_ie[1];
0433 if (ssid_len > IEEE80211_MAX_SSID_LEN)
0434 ssid_len = IEEE80211_MAX_SSID_LEN;
0435 memcpy(ssid, &ssid_ie[2], ssid_len);
0436 }
0437 rcu_read_unlock();
0438
0439 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
0440
0441 wvif->join_in_progress = true;
0442 ret = wfx_hif_join(wvif, conf, wvif->channel, ssid, ssid_len);
0443 if (ret) {
0444 ieee80211_connection_loss(vif);
0445 wfx_reset(wvif);
0446 } else {
0447
0448
0449
0450
0451 wfx_filter_beacon(wvif, false);
0452 }
0453 wfx_tx_unlock(wvif->wdev);
0454 }
0455
0456 static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info)
0457 {
0458 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0459 struct ieee80211_sta *sta = NULL;
0460 int ampdu_density = 0;
0461 bool greenfield = false;
0462
0463 rcu_read_lock();
0464 if (info->bssid && !vif->cfg.ibss_joined)
0465 sta = ieee80211_find_sta(vif, info->bssid);
0466 if (sta && sta->deflink.ht_cap.ht_supported)
0467 ampdu_density = sta->deflink.ht_cap.ampdu_density;
0468 if (sta && sta->deflink.ht_cap.ht_supported &&
0469 !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT))
0470 greenfield = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
0471 rcu_read_unlock();
0472
0473 wvif->join_in_progress = false;
0474 wfx_hif_set_association_mode(wvif, ampdu_density, greenfield, info->use_short_preamble);
0475 wfx_hif_keep_alive_period(wvif, 0);
0476
0477 wfx_hif_set_bss_params(wvif, vif->cfg.aid, 7);
0478 wfx_hif_set_beacon_wakeup_period(wvif, 1, 1);
0479 wfx_update_pm(wvif);
0480 }
0481
0482 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
0483 {
0484 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0485
0486 wfx_upload_ap_templates(wvif);
0487 wfx_join(wvif);
0488 return 0;
0489 }
0490
0491 void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
0492 {
0493 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0494
0495 wfx_reset(wvif);
0496 }
0497
0498 static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
0499 {
0500
0501
0502
0503
0504 if (!enable && wfx_tx_queues_has_cab(wvif)) {
0505 wvif->after_dtim_tx_allowed = true;
0506 wfx_bh_request_tx(wvif->wdev);
0507 }
0508 wfx_hif_beacon_transmit(wvif, enable);
0509 }
0510
0511 void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0512 struct ieee80211_bss_conf *info, u64 changed)
0513 {
0514 struct wfx_dev *wdev = hw->priv;
0515 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0516 int i;
0517
0518 mutex_lock(&wdev->conf_mutex);
0519
0520 if (changed & BSS_CHANGED_BASIC_RATES ||
0521 changed & BSS_CHANGED_BEACON_INT ||
0522 changed & BSS_CHANGED_BSSID) {
0523 if (vif->type == NL80211_IFTYPE_STATION)
0524 wfx_join(wvif);
0525 }
0526
0527 if (changed & BSS_CHANGED_ASSOC) {
0528 if (vif->cfg.assoc || vif->cfg.ibss_joined)
0529 wfx_join_finalize(wvif, info);
0530 else if (!vif->cfg.assoc && vif->type == NL80211_IFTYPE_STATION)
0531 wfx_reset(wvif);
0532 else
0533 dev_warn(wdev->dev, "misunderstood change: ASSOC\n");
0534 }
0535
0536 if (changed & BSS_CHANGED_BEACON_INFO) {
0537 if (vif->type != NL80211_IFTYPE_STATION)
0538 dev_warn(wdev->dev, "misunderstood change: BEACON_INFO\n");
0539 wfx_hif_set_beacon_wakeup_period(wvif, info->dtim_period, info->dtim_period);
0540
0541 wfx_filter_beacon(wvif, true);
0542 }
0543
0544 if (changed & BSS_CHANGED_ARP_FILTER) {
0545 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
0546 __be32 *arp_addr = &vif->cfg.arp_addr_list[i];
0547
0548 if (vif->cfg.arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
0549 arp_addr = NULL;
0550 if (i >= vif->cfg.arp_addr_cnt)
0551 arp_addr = NULL;
0552 wfx_hif_set_arp_ipv4_filter(wvif, i, arp_addr);
0553 }
0554 }
0555
0556 if (changed & BSS_CHANGED_AP_PROBE_RESP || changed & BSS_CHANGED_BEACON)
0557 wfx_upload_ap_templates(wvif);
0558
0559 if (changed & BSS_CHANGED_BEACON_ENABLED)
0560 wfx_enable_beacon(wvif, info->enable_beacon);
0561
0562 if (changed & BSS_CHANGED_KEEP_ALIVE)
0563 wfx_hif_keep_alive_period(wvif,
0564 info->max_idle_period * USEC_PER_TU / USEC_PER_MSEC);
0565
0566 if (changed & BSS_CHANGED_ERP_CTS_PROT)
0567 wfx_hif_erp_use_protection(wvif, info->use_cts_prot);
0568
0569 if (changed & BSS_CHANGED_ERP_SLOT)
0570 wfx_hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
0571
0572 if (changed & BSS_CHANGED_CQM)
0573 wfx_hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold, info->cqm_rssi_hyst);
0574
0575 if (changed & BSS_CHANGED_TXPOWER)
0576 wfx_hif_set_output_power(wvif, info->txpower);
0577
0578 if (changed & BSS_CHANGED_PS)
0579 wfx_update_pm(wvif);
0580
0581 mutex_unlock(&wdev->conf_mutex);
0582 }
0583
0584 static int wfx_update_tim(struct wfx_vif *wvif)
0585 {
0586 struct ieee80211_vif *vif = wvif_to_vif(wvif);
0587 struct sk_buff *skb;
0588 u16 tim_offset, tim_length;
0589 u8 *tim_ptr;
0590
0591 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, vif, &tim_offset,
0592 &tim_length, 0);
0593 if (!skb)
0594 return -ENOENT;
0595 tim_ptr = skb->data + tim_offset;
0596
0597 if (tim_offset && tim_length >= 6) {
0598
0599 tim_ptr[2] = 0;
0600
0601
0602 if (wfx_tx_queues_has_cab(wvif))
0603 tim_ptr[4] |= 1;
0604 else
0605 tim_ptr[4] &= ~1;
0606 }
0607
0608 wfx_hif_update_ie_beacon(wvif, tim_ptr, tim_length);
0609 dev_kfree_skb(skb);
0610
0611 return 0;
0612 }
0613
0614 static void wfx_update_tim_work(struct work_struct *work)
0615 {
0616 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
0617
0618 wfx_update_tim(wvif);
0619 }
0620
0621 int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
0622 {
0623 struct wfx_dev *wdev = hw->priv;
0624 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
0625 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
0626
0627 if (!wvif) {
0628 dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__);
0629 return -EIO;
0630 }
0631 schedule_work(&wvif->update_tim_work);
0632 return 0;
0633 }
0634
0635 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
0636 {
0637 struct wfx_vif *wvif_it;
0638
0639 if (notify_cmd != STA_NOTIFY_AWAKE)
0640 return;
0641
0642
0643
0644
0645 wvif_it = NULL;
0646 while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL)
0647 if (mutex_is_locked(&wvif_it->scan_lock))
0648 return;
0649
0650 if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed)
0651 dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)",
0652 wfx_tx_queues_has_cab(wvif));
0653 wvif->after_dtim_tx_allowed = true;
0654 wfx_bh_request_tx(wvif->wdev);
0655 }
0656
0657 int wfx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0658 struct ieee80211_ampdu_params *params)
0659 {
0660
0661 switch (params->action) {
0662 case IEEE80211_AMPDU_RX_START:
0663 case IEEE80211_AMPDU_RX_STOP:
0664
0665 return 0;
0666 default:
0667
0668 return -EOPNOTSUPP;
0669 }
0670 }
0671
0672 int wfx_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf)
0673 {
0674 return 0;
0675 }
0676
0677 void wfx_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf)
0678 {
0679 }
0680
0681 void wfx_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf, u32 changed)
0682 {
0683 }
0684
0685 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0686 struct ieee80211_bss_conf *link_conf,
0687 struct ieee80211_chanctx_conf *conf)
0688 {
0689 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0690 struct ieee80211_channel *ch = conf->def.chan;
0691
0692 WARN(wvif->channel, "channel overwrite");
0693 wvif->channel = ch;
0694
0695 return 0;
0696 }
0697
0698 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
0699 struct ieee80211_bss_conf *link_conf,
0700 struct ieee80211_chanctx_conf *conf)
0701 {
0702 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0703 struct ieee80211_channel *ch = conf->def.chan;
0704
0705 WARN(wvif->channel != ch, "channel mismatch");
0706 wvif->channel = NULL;
0707 }
0708
0709 int wfx_config(struct ieee80211_hw *hw, u32 changed)
0710 {
0711 return 0;
0712 }
0713
0714 int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
0715 {
0716 int i;
0717 struct wfx_dev *wdev = hw->priv;
0718 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0719
0720 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
0721 IEEE80211_VIF_SUPPORTS_UAPSD |
0722 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
0723
0724 mutex_lock(&wdev->conf_mutex);
0725
0726 switch (vif->type) {
0727 case NL80211_IFTYPE_STATION:
0728 case NL80211_IFTYPE_ADHOC:
0729 case NL80211_IFTYPE_AP:
0730 break;
0731 default:
0732 mutex_unlock(&wdev->conf_mutex);
0733 return -EOPNOTSUPP;
0734 }
0735
0736 wvif->wdev = wdev;
0737
0738 wvif->link_id_map = 1;
0739 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
0740 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
0741
0742 init_completion(&wvif->set_pm_mode_complete);
0743 complete(&wvif->set_pm_mode_complete);
0744 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
0745
0746 mutex_init(&wvif->scan_lock);
0747 init_completion(&wvif->scan_complete);
0748 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
0749
0750 wfx_tx_queues_init(wvif);
0751 wfx_tx_policy_init(wvif);
0752
0753 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
0754 if (!wdev->vif[i]) {
0755 wdev->vif[i] = vif;
0756 wvif->id = i;
0757 break;
0758 }
0759 }
0760 WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported");
0761
0762 wfx_hif_set_macaddr(wvif, vif->addr);
0763
0764 mutex_unlock(&wdev->conf_mutex);
0765
0766 wvif = NULL;
0767 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
0768
0769 if (wvif_count(wdev) == 1)
0770 wfx_hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
0771 else
0772 wfx_hif_set_block_ack_policy(wvif, 0x00, 0x00);
0773 }
0774 return 0;
0775 }
0776
0777 void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
0778 {
0779 struct wfx_dev *wdev = hw->priv;
0780 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
0781
0782 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
0783 wfx_tx_queues_check_empty(wvif);
0784
0785 mutex_lock(&wdev->conf_mutex);
0786 WARN(wvif->link_id_map != 1, "corrupted state");
0787
0788 wfx_hif_reset(wvif, false);
0789 wfx_hif_set_macaddr(wvif, NULL);
0790 wfx_tx_policy_init(wvif);
0791
0792 cancel_delayed_work_sync(&wvif->beacon_loss_work);
0793 wdev->vif[wvif->id] = NULL;
0794
0795 mutex_unlock(&wdev->conf_mutex);
0796
0797 wvif = NULL;
0798 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
0799
0800 if (wvif_count(wdev) == 1)
0801 wfx_hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
0802 else
0803 wfx_hif_set_block_ack_policy(wvif, 0x00, 0x00);
0804 }
0805 }
0806
0807 int wfx_start(struct ieee80211_hw *hw)
0808 {
0809 return 0;
0810 }
0811
0812 void wfx_stop(struct ieee80211_hw *hw)
0813 {
0814 struct wfx_dev *wdev = hw->priv;
0815
0816 WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending));
0817 }