staging: wfx: fix double init of tx_policy_upload_work
[linux-2.6-microblaze.git] / drivers / staging / wfx / sta.c
index 7255899..74ec0b6 100644 (file)
@@ -38,91 +38,31 @@ u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
        return ret;
 }
 
-static void __wfx_free_event_queue(struct list_head *list)
+void wfx_cooling_timeout_work(struct work_struct *work)
 {
-       struct wfx_hif_event *event, *tmp;
+       struct wfx_dev *wdev = container_of(to_delayed_work(work),
+                                           struct wfx_dev,
+                                           cooling_timeout_work);
 
-       list_for_each_entry_safe(event, tmp, list, link) {
-               list_del(&event->link);
-               kfree(event);
-       }
-}
-
-static void wfx_free_event_queue(struct wfx_vif *wvif)
-{
-       LIST_HEAD(list);
-
-       spin_lock(&wvif->event_queue_lock);
-       list_splice_init(&wvif->event_queue, &list);
-       spin_unlock(&wvif->event_queue_lock);
-
-       __wfx_free_event_queue(&list);
+       wdev->chip_frozen = true;
+       wfx_tx_unlock(wdev);
 }
 
-void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad)
+void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd)
 {
-       int tx = 0;
-
-       mutex_lock(&wvif->bss_loss_lock);
-       cancel_work_sync(&wvif->bss_params_work);
-
-       if (init) {
-               schedule_delayed_work(&wvif->bss_loss_work, HZ);
-               wvif->bss_loss_state = 0;
-
-               if (!atomic_read(&wvif->wdev->tx_lock))
-                       tx = 1;
-       } else if (good) {
-               cancel_delayed_work_sync(&wvif->bss_loss_work);
-               wvif->bss_loss_state = 0;
-               schedule_work(&wvif->bss_params_work);
-       } else if (bad) {
-               /* FIXME Should we just keep going until we time out? */
-               if (wvif->bss_loss_state < 3)
-                       tx = 1;
+       if (cmd == STA_NOTIFY_AWAKE) {
+               // Device recover normal temperature
+               if (cancel_delayed_work(&wdev->cooling_timeout_work))
+                       wfx_tx_unlock(wdev);
        } else {
-               cancel_delayed_work_sync(&wvif->bss_loss_work);
-               wvif->bss_loss_state = 0;
-       }
-
-       /* Spit out a NULL packet to our AP if necessary */
-       // FIXME: call ieee80211_beacon_loss/ieee80211_connection_loss instead
-       if (tx) {
-               struct sk_buff *skb;
-               struct ieee80211_hdr *hdr;
-               struct ieee80211_tx_control control = { };
-
-               wvif->bss_loss_state++;
-
-               skb = ieee80211_nullfunc_get(wvif->wdev->hw, wvif->vif, false);
-               if (!skb)
-                       goto end;
-               hdr = (struct ieee80211_hdr *)skb->data;
-               memset(IEEE80211_SKB_CB(skb), 0,
-                      sizeof(*IEEE80211_SKB_CB(skb)));
-               IEEE80211_SKB_CB(skb)->control.vif = wvif->vif;
-               IEEE80211_SKB_CB(skb)->driver_rates[0].idx = 0;
-               IEEE80211_SKB_CB(skb)->driver_rates[0].count = 1;
-               IEEE80211_SKB_CB(skb)->driver_rates[1].idx = -1;
-               rcu_read_lock(); // protect control.sta
-               control.sta = ieee80211_find_sta(wvif->vif, hdr->addr1);
-               wfx_tx(wvif->wdev->hw, &control, skb);
-               rcu_read_unlock();
+               // Device is too hot
+               schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ);
+               wfx_tx_lock(wdev);
        }
-end:
-       mutex_unlock(&wvif->bss_loss_lock);
 }
 
-int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable)
+static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
 {
-       wvif->fwd_probe_req = enable;
-       return hif_set_rx_filter(wvif, wvif->filter_bssid,
-                                wvif->fwd_probe_req);
-}
-
-void wfx_update_filtering(struct wfx_vif *wvif)
-{
-       int i;
        const struct hif_ie_table_entry filter_ies[] = {
                {
                        .ie_id        = WLAN_EID_VENDOR_SPECIFIC,
@@ -143,34 +83,33 @@ void wfx_update_filtering(struct wfx_vif *wvif)
                }
        };
 
-       hif_set_rx_filter(wvif, wvif->filter_bssid, wvif->fwd_probe_req);
-       if (wvif->disable_beacon_filter) {
+       if (!filter_beacon) {
                hif_set_beacon_filter_table(wvif, 0, NULL);
                hif_beacon_filter_control(wvif, 0, 1);
-       } else if (wvif->vif->type != NL80211_IFTYPE_STATION) {
-               hif_set_beacon_filter_table(wvif, 2, filter_ies);
-               hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE |
-                                               HIF_BEACON_FILTER_AUTO_ERP, 0);
        } else {
                hif_set_beacon_filter_table(wvif, 3, filter_ies);
                hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
        }
+}
+
+static void wfx_filter_mcast(struct wfx_vif *wvif, bool filter_mcast)
+{
+       int i;
 
        // Temporary workaround for filters
        hif_set_data_filtering(wvif, false, true);
        return;
 
-       if (!wvif->mcast_filter.enable) {
+       if (!filter_mcast) {
                hif_set_data_filtering(wvif, false, true);
                return;
        }
-       for (i = 0; i < wvif->mcast_filter.num_addresses; i++)
-               hif_set_mac_addr_condition(wvif, i,
-                                          wvif->mcast_filter.address_list[i]);
+       for (i = 0; i < wvif->filter_mcast_count; i++)
+               hif_set_mac_addr_condition(wvif, i, wvif->filter_mcast_addr[i]);
        hif_set_uc_mc_bc_condition(wvif, 0,
                                   HIF_FILTER_UNICAST | HIF_FILTER_BROADCAST);
        hif_set_config_data_filter(wvif, true, 0, BIT(1),
-                                  BIT(wvif->mcast_filter.num_addresses) - 1);
+                                  BIT(wvif->filter_mcast_count) - 1);
        hif_set_data_filtering(wvif, true, true);
 }
 
@@ -184,18 +123,17 @@ u64 wfx_prepare_multicast(struct ieee80211_hw *hw,
        int count = netdev_hw_addr_list_count(mc_list);
 
        while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
-               memset(&wvif->mcast_filter, 0x00, sizeof(wvif->mcast_filter));
-               if (!count ||
-                   count > ARRAY_SIZE(wvif->mcast_filter.address_list))
+               if (count > ARRAY_SIZE(wvif->filter_mcast_addr)) {
+                       wvif->filter_mcast_count = 0;
                        continue;
+               }
+               wvif->filter_mcast_count = count;
 
                i = 0;
                netdev_hw_addr_list_for_each(ha, mc_list) {
-                       ether_addr_copy(wvif->mcast_filter.address_list[i],
-                                       ha->addr);
+                       ether_addr_copy(wvif->filter_mcast_addr[i], ha->addr);
                        i++;
                }
-               wvif->mcast_filter.num_addresses = count;
        }
 
        return 0;
@@ -208,6 +146,7 @@ void wfx_configure_filter(struct ieee80211_hw *hw,
 {
        struct wfx_vif *wvif = NULL;
        struct wfx_dev *wdev = hw->priv;
+       bool filter_bssid, filter_prbreq, filter_beacon, filter_mcast;
 
        // Notes:
        //   - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
@@ -226,29 +165,39 @@ void wfx_configure_filter(struct ieee80211_hw *hw,
                // Note: FIF_BCN_PRBRESP_PROMISC covers probe response and
                // beacons from other BSS
                if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
-                       wvif->disable_beacon_filter = true;
+                       filter_beacon = false;
                else
-                       wvif->disable_beacon_filter = false;
+                       filter_beacon = true;
+               wfx_filter_beacon(wvif, filter_beacon);
 
                if (*total_flags & FIF_ALLMULTI) {
-                       wvif->mcast_filter.enable = false;
-               } else if (!wvif->mcast_filter.num_addresses) {
+                       filter_mcast = false;
+               } else if (!wvif->filter_mcast_count) {
                        dev_dbg(wdev->dev, "disabling unconfigured multicast filter");
-                       wvif->mcast_filter.enable = false;
+                       filter_mcast = false;
                } else {
-                       wvif->mcast_filter.enable = true;
+                       filter_mcast = true;
                }
-               wfx_update_filtering(wvif);
+               wfx_filter_mcast(wvif, filter_mcast);
 
                if (*total_flags & FIF_OTHER_BSS)
-                       wvif->filter_bssid = false;
+                       filter_bssid = false;
                else
-                       wvif->filter_bssid = true;
+                       filter_bssid = true;
+
+               // In AP mode, chip can reply to probe request itself
+               if (*total_flags & FIF_PROBE_REQ &&
+                   wvif->vif->type == NL80211_IFTYPE_AP) {
+                       dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
+                       *total_flags &= ~FIF_PROBE_REQ;
+               }
 
                if (*total_flags & FIF_PROBE_REQ)
-                       wfx_fwd_probe_req(wvif, true);
+                       filter_prbreq = false;
                else
-                       wfx_fwd_probe_req(wvif, false);
+                       filter_prbreq = true;
+               hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
+
                mutex_unlock(&wvif->scan_lock);
        }
        mutex_unlock(&wdev->conf_mutex);
@@ -262,7 +211,7 @@ static int wfx_update_pm(struct wfx_vif *wvif)
        struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
 
        WARN_ON(conf->dynamic_ps_timeout < 0);
-       if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid)
+       if (!wvif->vif->bss_conf.assoc)
                return 0;
        if (!ps)
                ps_timeout = 0;
@@ -279,7 +228,10 @@ static int wfx_update_pm(struct wfx_vif *wvif)
        if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
            wvif->vif->type != NL80211_IFTYPE_AP) {
                ps = true;
-               ps_timeout = 0;
+               if (wvif->bss_not_support_ps_poll)
+                       ps_timeout = 30;
+               else
+                       ps_timeout = 0;
        }
 
        if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
@@ -289,6 +241,14 @@ static int wfx_update_pm(struct wfx_vif *wvif)
        return hif_set_pm(wvif, ps, ps_timeout);
 }
 
+static void wfx_update_pm_work(struct work_struct *work)
+{
+       struct wfx_vif *wvif = container_of(work, struct wfx_vif,
+                                           update_pm_work);
+
+       wfx_update_pm(wvif);
+}
+
 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                   u16 queue, const struct ieee80211_tx_queue_params *params)
 {
@@ -322,7 +282,7 @@ int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 
 /* WSM callbacks */
 
-static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
+void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
 {
        /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
         * RSSI = RCPI / 2 - 110
@@ -338,91 +298,37 @@ static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
        ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
 }
 
-static void wfx_event_handler_work(struct work_struct *work)
-{
-       struct wfx_vif *wvif =
-               container_of(work, struct wfx_vif, event_handler_work);
-       struct wfx_hif_event *event;
-
-       LIST_HEAD(list);
-
-       spin_lock(&wvif->event_queue_lock);
-       list_splice_init(&wvif->event_queue, &list);
-       spin_unlock(&wvif->event_queue_lock);
-
-       list_for_each_entry(event, &list, link) {
-               switch (event->evt.event_id) {
-               case HIF_EVENT_IND_BSSLOST:
-                       mutex_lock(&wvif->scan_lock);
-                       wfx_cqm_bssloss_sm(wvif, 1, 0, 0);
-                       mutex_unlock(&wvif->scan_lock);
-                       break;
-               case HIF_EVENT_IND_BSSREGAINED:
-                       wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
-                       break;
-               case HIF_EVENT_IND_RCPI_RSSI:
-                       wfx_event_report_rssi(wvif,
-                                             event->evt.event_data.rcpi_rssi);
-                       break;
-               case HIF_EVENT_IND_PS_MODE_ERROR:
-                       dev_warn(wvif->wdev->dev,
-                                "error while processing power save request\n");
-                       break;
-               default:
-                       dev_warn(wvif->wdev->dev,
-                                "unhandled event indication: %.2x\n",
-                                event->evt.event_id);
-                       break;
-               }
-       }
-       __wfx_free_event_queue(&list);
-}
-
-static void wfx_bss_loss_work(struct work_struct *work)
+static void wfx_beacon_loss_work(struct work_struct *work)
 {
-       struct wfx_vif *wvif = container_of(work, struct wfx_vif,
-                                           bss_loss_work.work);
+       struct wfx_vif *wvif = container_of(to_delayed_work(work),
+                                           struct wfx_vif, beacon_loss_work);
+       struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
 
-       ieee80211_connection_loss(wvif->vif);
+       ieee80211_beacon_loss(wvif->vif);
+       schedule_delayed_work(to_delayed_work(work),
+                             msecs_to_jiffies(bss_conf->beacon_int));
 }
 
-static void wfx_bss_params_work(struct work_struct *work)
+void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif, int idx)
 {
-       struct wfx_vif *wvif = container_of(work, struct wfx_vif,
-                                           bss_params_work);
+       struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 
-       mutex_lock(&wvif->wdev->conf_mutex);
-       wvif->bss_params.bss_flags.lost_count_only = 1;
-       hif_set_bss_params(wvif, &wvif->bss_params);
-       wvif->bss_params.bss_flags.lost_count_only = 0;
-       mutex_unlock(&wvif->wdev->conf_mutex);
+       hif_wep_default_key_id(wvif, idx);
 }
 
 // Call it with wdev->conf_mutex locked
 static void wfx_do_unjoin(struct wfx_vif *wvif)
 {
-       if (!wvif->state)
-               return;
-
-       if (wvif->state == WFX_STATE_AP)
-               return;
-
-       wvif->state = WFX_STATE_PASSIVE;
-
        /* Unjoin is a reset. */
        wfx_tx_lock_flush(wvif->wdev);
        hif_reset(wvif, false);
        wfx_tx_policy_init(wvif);
        if (wvif_count(wvif->wdev) <= 1)
                hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
-       wfx_free_event_queue(wvif);
-       cancel_work_sync(&wvif->event_handler_work);
-       wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
-
-       wvif->disable_beacon_filter = false;
-       wfx_update_filtering(wvif);
-       memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
        wfx_tx_unlock(wvif->wdev);
+       wvif->bss_not_support_ps_poll = false;
+       cancel_delayed_work_sync(&wvif->beacon_loss_work);
 }
 
 static void wfx_set_mfp(struct wfx_vif *wvif,
@@ -480,7 +386,9 @@ static void wfx_do_join(struct wfx_vif *wvif)
                ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
        if (ssidie) {
                ssidlen = ssidie[1];
-               memcpy(ssid, &ssidie[2], ssidie[1]);
+               if (ssidlen > IEEE80211_MAX_SSID_LEN)
+                       ssidlen = IEEE80211_MAX_SSID_LEN;
+               memcpy(ssid, &ssidie[2], ssidlen);
        }
        rcu_read_unlock();
 
@@ -490,25 +398,14 @@ static void wfx_do_join(struct wfx_vif *wvif)
        ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
        if (ret) {
                ieee80211_connection_loss(wvif->vif);
-               wvif->join_complete_status = -1;
                wfx_do_unjoin(wvif);
        } else {
-               wvif->join_complete_status = 0;
-               if (wvif->vif->type == NL80211_IFTYPE_ADHOC)
-                       wvif->state = WFX_STATE_IBSS;
-               else
-                       wvif->state = WFX_STATE_PRE_STA;
-
-               /* Upload keys */
-               wfx_upload_keys(wvif);
-
                /* Due to beacon filtering it is possible that the
                 * AP's beacon is not known for the mac80211 stack.
                 * Disable filtering temporary to make sure the stack
                 * receives at least one
                 */
-               wvif->disable_beacon_filter = true;
-               wfx_update_filtering(wvif);
+               wfx_filter_beacon(wvif, false);
        }
        wfx_tx_unlock(wvif->wdev);
 }
@@ -522,9 +419,8 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        spin_lock_init(&sta_priv->lock);
        sta_priv->vif_id = wvif->id;
 
-       // FIXME: in station mode, the current API interprets new link-id as a
-       // tdls peer.
-       if (vif->type == NL80211_IFTYPE_STATION)
+       // In station mode, the firmware interprets new link-id as a TDLS peer.
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
                return 0;
        sta_priv->link_id = ffz(wvif->link_id_map);
        wvif->link_id_map |= BIT(sta_priv->link_id);
@@ -546,8 +442,8 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                if (sta_priv->buffered[i])
                        dev_warn(wvif->wdev->dev, "release station while %d pending frame on queue %d",
                                 sta_priv->buffered[i], i);
-       // FIXME: see note in wfx_sta_add()
-       if (vif->type == NL80211_IFTYPE_STATION)
+       // See note in wfx_sta_add()
+       if (!sta_priv->link_id)
                return 0;
        // FIXME add a mutex?
        hif_map_link(wvif, sta->addr, 1, sta_priv->link_id);
@@ -579,11 +475,7 @@ int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
 
-       wfx_upload_keys(wvif);
-       wvif->state = WFX_STATE_AP;
-       wfx_update_filtering(wvif);
        wfx_upload_ap_templates(wvif);
-       wfx_fwd_probe_req(wvif, false);
        hif_start(wvif, &vif->bss_conf, wvif->channel);
        return 0;
 }
@@ -596,44 +488,19 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        wfx_tx_policy_init(wvif);
        if (wvif_count(wvif->wdev) <= 1)
                hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
-       wvif->state = WFX_STATE_PASSIVE;
+       wvif->bss_not_support_ps_poll = false;
 }
 
 static void wfx_join_finalize(struct wfx_vif *wvif,
                              struct ieee80211_bss_conf *info)
 {
-       struct ieee80211_sta *sta = NULL;
-
-       rcu_read_lock(); // protect sta
-       if (info->bssid && !info->ibss_joined)
-               sta = ieee80211_find_sta(wvif->vif, info->bssid);
-       if (sta)
-               wvif->bss_params.operational_rate_set =
-                       wfx_rate_mask_to_hw(wvif->wdev, sta->supp_rates[wvif->channel->band]);
-       else
-               wvif->bss_params.operational_rate_set = -1;
-       rcu_read_unlock();
-       if (sta &&
-           info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
-               hif_dual_cts_protection(wvif, true);
-       else
-               hif_dual_cts_protection(wvif, false);
-
-       wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
-
-       wvif->bss_params.beacon_lost_count = 20;
-       wvif->bss_params.aid = info->aid;
-
        hif_set_association_mode(wvif, info);
-
-       if (!info->ibss_joined) {
-               wvif->state = WFX_STATE_STA;
-               hif_keep_alive_period(wvif, 0);
-               hif_set_bss_params(wvif, &wvif->bss_params);
-               hif_set_beacon_wakeup_period(wvif, info->dtim_period,
-                                            info->dtim_period);
-               wfx_update_pm(wvif);
-       }
+       hif_keep_alive_period(wvif, 0);
+       // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
+       // the same value.
+       hif_set_bss_params(wvif, info->aid, 7);
+       hif_set_beacon_wakeup_period(wvif, 1, 1);
+       wfx_update_pm(wvif);
 }
 
 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
@@ -711,15 +578,7 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw,
                                             info->dtim_period);
                // We temporary forwarded beacon for join process. It is now no
                // more necessary.
-               wvif->disable_beacon_filter = false;
-               wfx_update_filtering(wvif);
-       }
-
-       /* assoc/disassoc, or maybe AID changed */
-       if (changed & BSS_CHANGED_ASSOC) {
-               wfx_tx_lock_flush(wdev);
-               wvif->wep_default_key_id = -1;
-               wfx_tx_unlock(wdev);
+               wfx_filter_beacon(wvif, true);
        }
 
        if (changed & BSS_CHANGED_ASSOC) {
@@ -805,6 +664,8 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
 
 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
 {
+       if (notify_cmd != STA_NOTIFY_AWAKE)
+               return;
        WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
        WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
        wvif->after_dtim_tx_allowed = true;
@@ -910,29 +771,17 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        wvif->link_id_map = 1; // link-id 0 is reserved for multicast
        INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
-
-       memset(&wvif->bss_params, 0, sizeof(wvif->bss_params));
-
-       mutex_init(&wvif->bss_loss_lock);
-       INIT_DELAYED_WORK(&wvif->bss_loss_work, wfx_bss_loss_work);
-
-       wvif->wep_default_key_id = -1;
-       INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work);
-
-       spin_lock_init(&wvif->event_queue_lock);
-       INIT_LIST_HEAD(&wvif->event_queue);
-       INIT_WORK(&wvif->event_handler_work, wfx_event_handler_work);
+       INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
 
        init_completion(&wvif->set_pm_mode_complete);
        complete(&wvif->set_pm_mode_complete);
-       INIT_WORK(&wvif->bss_params_work, wfx_bss_params_work);
+       INIT_WORK(&wvif->update_pm_work, wfx_update_pm_work);
        INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
 
        mutex_init(&wvif->scan_lock);
        init_completion(&wvif->scan_complete);
        INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
 
-       INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
        mutex_unlock(&wdev->conf_mutex);
 
        hif_set_macaddr(wvif, vif->addr);
@@ -961,28 +810,12 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&wdev->conf_mutex);
        WARN(wvif->link_id_map != 1, "corrupted state");
-       switch (wvif->state) {
-       case WFX_STATE_PRE_STA:
-       case WFX_STATE_STA:
-       case WFX_STATE_IBSS:
-               wfx_do_unjoin(wvif);
-               break;
-       case WFX_STATE_AP:
-               /* reset.link_id = 0; */
-               hif_reset(wvif, false);
-               break;
-       default:
-               break;
-       }
-
-       wvif->state = WFX_STATE_PASSIVE;
 
-       /* FIXME: In add to reset MAC address, try to reset interface */
+       hif_reset(wvif, false);
        hif_set_macaddr(wvif, NULL);
+       wfx_tx_policy_init(wvif);
 
-       wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
-       wfx_free_event_queue(wvif);
-
+       cancel_delayed_work_sync(&wvif->beacon_loss_work);
        wdev->vif[wvif->id] = NULL;
        wvif->vif = NULL;