mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
 
-mt76-connac-lib-y := mt76_connac_mcu.o
+mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
 
 obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
 obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
 
        mt7615_mac_sta_poll(dev);
        rcu_read_unlock();
 
-       mt7615_pm_power_save_sched(dev);
+       mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
        mt76_worker_schedule(&dev->mt76.tx_worker);
 }
 
 {
        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
 
-       if (mt7615_pm_wake(dev))
+       if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
                return;
 
        __mt7615_update_channel(dev);
-       mt7615_pm_power_save_sched(dev);
+       mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
 }
 EXPORT_SYMBOL_GPL(mt7615_update_channel);
 
 {
        struct mt7615_dev *dev;
        struct mt76_phy *mphy;
-       int i;
 
        dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,
                                                pm.wake_work);
        mphy = dev->phy.mt76;
 
-       if (mt7615_mcu_set_drv_ctrl(dev)) {
+       if (!mt7615_mcu_set_drv_ctrl(dev))
+               mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
+       else
                dev_err(mphy->dev->dev, "failed to wake device\n");
-               goto out;
-       }
-
-       spin_lock_bh(&dev->pm.txq_lock);
-       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-               struct mt76_wcid *wcid = dev->pm.tx_q[i].wcid;
-               struct ieee80211_sta *sta = NULL;
-
-               if (!dev->pm.tx_q[i].skb)
-                       continue;
-
-               if (wcid && wcid->sta)
-                       sta = container_of((void *)wcid, struct ieee80211_sta,
-                                          drv_priv);
-
-               mt76_tx(mphy, sta, wcid, dev->pm.tx_q[i].skb);
-               dev->pm.tx_q[i].skb = NULL;
-       }
-       spin_unlock_bh(&dev->pm.txq_lock);
-
-       mt76_worker_schedule(&dev->mt76.tx_worker);
 
-out:
        ieee80211_wake_queues(mphy->hw);
        complete_all(&dev->pm.wake_cmpl);
 }
 
-int mt7615_pm_wake(struct mt7615_dev *dev)
-{
-       struct mt76_phy *mphy = dev->phy.mt76;
-
-       if (!mt7615_firmware_offload(dev))
-               return 0;
-
-       if (!mt76_is_mmio(mphy->dev))
-               return 0;
-
-       if (!test_bit(MT76_STATE_PM, &mphy->state))
-               return 0;
-
-       if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
-           test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
-               return 0;
-
-       if (queue_work(dev->mt76.wq, &dev->pm.wake_work))
-               reinit_completion(&dev->pm.wake_cmpl);
-
-       if (!wait_for_completion_timeout(&dev->pm.wake_cmpl, 3 * HZ)) {
-               ieee80211_wake_queues(mphy->hw);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mt7615_pm_wake);
-
-void mt7615_pm_power_save_sched(struct mt7615_dev *dev)
-{
-       struct mt76_phy *mphy = dev->phy.mt76;
-
-       if (!mt7615_firmware_offload(dev))
-               return;
-
-       if (!mt76_is_mmio(mphy->dev))
-               return;
-
-       if (!dev->pm.enable || !test_bit(MT76_STATE_RUNNING, &mphy->state))
-               return;
-
-       dev->pm.last_activity = jiffies;
-
-       if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
-           test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
-               return;
-
-       if (!test_bit(MT76_STATE_PM, &mphy->state))
-               queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work,
-                                  dev->pm.idle_timeout);
-}
-EXPORT_SYMBOL_GPL(mt7615_pm_power_save_sched);
-
 void mt7615_pm_power_save_work(struct work_struct *work)
 {
        struct mt7615_dev *dev;
 
        return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
 }
 
-static void mt7615_free_pending_tx_skbs(struct mt7615_dev *dev,
-                                       struct mt7615_sta *msta)
-{
-       int i;
-
-       spin_lock_bh(&dev->pm.txq_lock);
-       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-               if (msta && dev->pm.tx_q[i].wcid != &msta->wcid)
-                       continue;
-
-               dev_kfree_skb(dev->pm.tx_q[i].skb);
-               dev->pm.tx_q[i].skb = NULL;
-       }
-       spin_unlock_bh(&dev->pm.txq_lock);
-}
-
 static int mt7615_start(struct ieee80211_hw *hw)
 {
        struct mt7615_dev *dev = mt7615_hw_dev(hw);
        cancel_delayed_work_sync(&dev->pm.ps_work);
        cancel_work_sync(&dev->pm.wake_work);
 
-       mt7615_free_pending_tx_skbs(dev, NULL);
+       mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
 
        mt7615_mutex_acquire(dev);
 
        if (vif == phy->monitor_vif)
            phy->monitor_vif = NULL;
 
-       mt7615_free_pending_tx_skbs(dev, msta);
+       mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
 
        mt7615_mac_set_beacon_filter(phy, vif, false);
        mt7615_mcu_add_dev_info(phy, vif, false);
        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
        struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
        struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
+       struct mt7615_phy *phy;
        int idx, err;
 
        idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
        msta->wcid.idx = idx;
        msta->wcid.ext_phy = mvif->mt76.band_idx;
 
-       err = mt7615_pm_wake(dev);
+       phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
+       err = mt76_connac_pm_wake(phy->mt76, &dev->pm);
        if (err)
                return err;
 
-       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
-               struct mt7615_phy *phy;
-
-               phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
                mt7615_mcu_add_bss_info(phy, vif, sta, true);
-       }
        mt7615_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
        mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
 
-       mt7615_pm_power_save_sched(dev);
+       mt76_connac_power_save_sched(phy->mt76, &dev->pm);
 
        return 0;
 }
 {
        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
        struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
+       struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
+       struct mt7615_phy *phy;
+
+       mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
 
-       mt7615_free_pending_tx_skbs(dev, msta);
-       mt7615_pm_wake(dev);
+       phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
+       mt76_connac_pm_wake(phy->mt76, &dev->pm);
 
        mt7615_mcu_sta_add(&dev->phy, vif, sta, false);
        mt7615_mac_wtbl_update(dev, msta->wcid.idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
-               struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
-               struct mt7615_phy *phy;
-
-               phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
                mt7615_mcu_add_bss_info(phy, vif, sta, false);
-       }
 
        spin_lock_bh(&dev->sta_poll_lock);
        if (!list_empty(&msta->poll_list))
                list_del_init(&msta->poll_list);
        spin_unlock_bh(&dev->sta_poll_lock);
 
-       mt7615_pm_power_save_sched(dev);
+       mt76_connac_power_save_sched(phy->mt76, &dev->pm);
 }
 EXPORT_SYMBOL_GPL(mt7615_mac_sta_remove);
 
                skb_set_queue_mapping(skb, qid);
        }
 
-       spin_lock_bh(&dev->pm.txq_lock);
-       if (!dev->pm.tx_q[qid].skb) {
-               ieee80211_stop_queues(hw);
-               dev->pm.tx_q[qid].wcid = wcid;
-               dev->pm.tx_q[qid].skb = skb;
-               queue_work(dev->mt76.wq, &dev->pm.wake_work);
-       } else {
-               dev_kfree_skb(skb);
-       }
-       spin_unlock_bh(&dev->pm.txq_lock);
+       mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);
 }
 
 static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
        int err = 0;
 
        cancel_delayed_work_sync(&dev->pm.ps_work);
-       mt7615_free_pending_tx_skbs(dev, NULL);
+       mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
 
        mt7615_mutex_acquire(dev);
 
 
                          struct ieee80211_tx_rate *probe_rate,
                          struct ieee80211_tx_rate *rates);
 void mt7615_pm_wake_work(struct work_struct *work);
-int mt7615_pm_wake(struct mt7615_dev *dev);
-void mt7615_pm_power_save_sched(struct mt7615_dev *dev);
 void mt7615_pm_power_save_work(struct work_struct *work);
 int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev);
 int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd);
                return MT7615_WTBL_SIZE;
 }
 
-static inline void mt7615_mutex_acquire(struct mt7615_dev *dev)
-        __acquires(&dev->mt76.mutex)
-{
-       mutex_lock(&dev->mt76.mutex);
-       mt7615_pm_wake(dev);
-}
-
-static inline void mt7615_mutex_release(struct mt7615_dev *dev)
-       __releases(&dev->mt76.mutex)
-{
-       mt7615_pm_power_save_sched(dev);
-       mutex_unlock(&dev->mt76.mutex);
-}
+#define mt7615_mutex_acquire(dev)      \
+       mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm)
+#define mt7615_mutex_release(dev)      \
+       mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
 
 static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac)
 {
 
        bool hif_suspend;
        int i, err;
 
-       err = mt7615_pm_wake(dev);
+       err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
        if (err < 0)
                return err;
 
 
 
 extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
 
+int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
+void mt76_connac_power_save_sched(struct mt76_phy *phy,
+                                 struct mt76_connac_pm *pm);
+void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
+                                     struct mt76_wcid *wcid);
+
+static inline void
+mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm)
+       __acquires(&dev->mutex)
+{
+       mutex_lock(&dev->mutex);
+       mt76_connac_pm_wake(&dev->phy, pm);
+}
+
+static inline void
+mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
+       __releases(&dev->mutex)
+{
+       mt76_connac_power_save_sched(&dev->phy, pm);
+       mutex_unlock(&dev->mutex);
+}
+
+void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
+                             struct mt76_connac_pm *pm,
+                             struct mt76_wcid *wcid,
+                             struct sk_buff *skb);
+void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
+                                struct mt76_connac_pm *pm);
+
 #endif /* __MT76_CONNAC_H */
 
--- /dev/null
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2020 MediaTek Inc. */
+
+#include "mt76_connac.h"
+
+int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
+{
+       struct mt76_dev *dev = phy->dev;
+
+       if (!pm->enable)
+               return 0;
+
+       if (!mt76_is_mmio(dev))
+               return 0;
+
+       if (!test_bit(MT76_STATE_PM, &phy->state))
+               return 0;
+
+       if (test_bit(MT76_HW_SCANNING, &phy->state) ||
+           test_bit(MT76_HW_SCHED_SCANNING, &phy->state))
+               return 0;
+
+       if (queue_work(dev->wq, &pm->wake_work))
+               reinit_completion(&pm->wake_cmpl);
+
+       if (!wait_for_completion_timeout(&pm->wake_cmpl, 3 * HZ)) {
+               ieee80211_wake_queues(phy->hw);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_connac_pm_wake);
+
+void mt76_connac_power_save_sched(struct mt76_phy *phy,
+                                 struct mt76_connac_pm *pm)
+{
+       struct mt76_dev *dev = phy->dev;
+
+       if (!mt76_is_mmio(dev))
+               return;
+
+       if (!pm->enable || !test_bit(MT76_STATE_RUNNING, &phy->state))
+               return;
+
+       pm->last_activity = jiffies;
+
+       if (test_bit(MT76_HW_SCANNING, &phy->state) ||
+           test_bit(MT76_HW_SCHED_SCANNING, &phy->state))
+               return;
+
+       if (!test_bit(MT76_STATE_PM, &phy->state))
+               queue_delayed_work(dev->wq, &pm->ps_work, pm->idle_timeout);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_power_save_sched);
+
+void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
+                                     struct mt76_wcid *wcid)
+{
+       int i;
+
+       spin_lock_bh(&pm->txq_lock);
+       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               if (wcid && pm->tx_q[i].wcid != wcid)
+                       continue;
+
+               dev_kfree_skb(pm->tx_q[i].skb);
+               pm->tx_q[i].skb = NULL;
+       }
+       spin_unlock_bh(&pm->txq_lock);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_free_pending_tx_skbs);
+
+void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
+                             struct mt76_connac_pm *pm,
+                             struct mt76_wcid *wcid,
+                             struct sk_buff *skb)
+{
+       int qid = skb_get_queue_mapping(skb);
+       struct mt76_phy *phy = hw->priv;
+
+       spin_lock_bh(&pm->txq_lock);
+       if (!pm->tx_q[qid].skb) {
+               ieee80211_stop_queues(hw);
+               pm->tx_q[qid].wcid = wcid;
+               pm->tx_q[qid].skb = skb;
+               queue_work(phy->dev->wq, &pm->wake_work);
+       } else {
+               dev_kfree_skb(skb);
+       }
+       spin_unlock_bh(&pm->txq_lock);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_pm_queue_skb);
+
+void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
+                                struct mt76_connac_pm *pm)
+{
+       int i;
+
+       spin_lock_bh(&pm->txq_lock);
+       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               struct mt76_wcid *wcid = pm->tx_q[i].wcid;
+               struct ieee80211_sta *sta = NULL;
+
+               if (!pm->tx_q[i].skb)
+                       continue;
+
+               if (wcid && wcid->sta)
+                       sta = container_of((void *)wcid, struct ieee80211_sta,
+                                          drv_priv);
+
+               mt76_tx(phy, sta, wcid, pm->tx_q[i].skb);
+               pm->tx_q[i].skb = NULL;
+       }
+       spin_unlock_bh(&pm->txq_lock);
+
+       mt76_worker_schedule(&phy->dev->tx_worker);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs);