mt7615_pm_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
+ int ret = 0;
if (!mt7615_wait_for_mcu_init(dev))
return 0;
- return mt7615_pm_set_enable(dev, val);
+ if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76))
+ return -EOPNOTSUPP;
+
+ mt7615_mutex_acquire(dev);
+
+ if (dev->phy.n_beacon_vif) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ dev->pm.enable = val;
+out:
+ mt7615_mutex_release(dev);
+
+ return ret;
}
static int
queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
}
-static void
-mt7615_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
-{
- struct mt7615_phy *phy = priv;
- struct mt7615_dev *dev = phy->dev;
- bool ext_phy = phy != &dev->phy;
-
- if (mt7615_mcu_set_bss_pm(dev, vif, dev->pm.enable))
- return;
-
- if (dev->pm.enable) {
- vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
- mt76_set(dev, MT_WF_RFCR(ext_phy),
- MT_WF_RFCR_DROP_OTHER_BEACON);
- } else {
- vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
- mt76_clear(dev, MT_WF_RFCR(ext_phy),
- MT_WF_RFCR_DROP_OTHER_BEACON);
- }
-}
-
-int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable)
-{
- struct mt76_phy *mphy = dev->phy.mt76;
-
- if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76))
- return -EOPNOTSUPP;
-
- mt7615_mutex_acquire(dev);
-
- if (dev->pm.enable == enable)
- goto out;
-
- dev->pm.enable = enable;
- ieee80211_iterate_active_interfaces(mphy->hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7615_pm_interface_iter, mphy->priv);
-out:
- mt7615_mutex_release(dev);
-
- return 0;
-}
-
void mt7615_mac_work(struct work_struct *work)
{
struct mt7615_phy *phy;
mt7615_dfs_stop_radar_detector(phy);
return 0;
}
+
+int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,
+ struct ieee80211_vif *vif,
+ bool enable)
+{
+ struct mt7615_dev *dev = phy->dev;
+ bool ext_phy = phy != &dev->phy;
+ int err;
+
+ if (!mt7615_firmware_offload(dev))
+ return -EOPNOTSUPP;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_MONITOR:
+ return 0;
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ if (enable)
+ phy->n_beacon_vif++;
+ else
+ phy->n_beacon_vif--;
+ fallthrough;
+ default:
+ break;
+ }
+
+ err = mt7615_mcu_set_bss_pm(dev, vif, !phy->n_beacon_vif);
+ if (err)
+ return err;
+
+ if (phy->n_beacon_vif) {
+ vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
+ mt76_clear(dev, MT_WF_RFCR(ext_phy),
+ MT_WF_RFCR_DROP_OTHER_BEACON);
+ } else {
+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+ mt76_set(dev, MT_WF_RFCR(ext_phy),
+ MT_WF_RFCR_DROP_OTHER_BEACON);
+ }
+
+ return 0;
+}
if (ret)
goto out;
- if (dev->pm.enable) {
- ret = mt7615_mcu_set_bss_pm(dev, vif, true);
- if (ret)
- goto out;
-
- vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
- mt76_set(dev, MT_WF_RFCR(ext_phy),
- MT_WF_RFCR_DROP_OTHER_BEACON);
- }
+ mt7615_mac_set_beacon_filter(phy, vif, true);
out:
mt7615_mutex_release(dev);
mt7615_free_pending_tx_skbs(dev, msta);
- if (dev->pm.enable) {
- bool ext_phy = phy != &dev->phy;
-
- mt7615_mcu_set_bss_pm(dev, vif, false);
- mt76_clear(dev, MT_WF_RFCR(ext_phy),
- MT_WF_RFCR_DROP_OTHER_BEACON);
- }
+ mt7615_mac_set_beacon_filter(phy, vif, false);
mt7615_mcu_add_dev_info(dev, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
} while (0)
phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
- MT_WF_RFCR_DROP_OTHER_BEACON |
MT_WF_RFCR_DROP_FRAME_REPORT |
MT_WF_RFCR_DROP_PROBEREQ |
MT_WF_RFCR_DROP_MCAST_FILTERED |
MT_WF_RFCR_DROP_UNWANTED_CTL |
MT_WF_RFCR_DROP_STBC_MULTI);
+ if (phy->n_beacon_vif || !mt7615_firmware_offload(dev))
+ phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_BEACON;
+
MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
MT_WF_RFCR_DROP_A3_MAC |
MT_WF_RFCR_DROP_A3_BSSID);
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
- bool ext_phy = phy != &dev->phy;
int err = 0;
cancel_delayed_work_sync(&dev->pm.ps_work);
cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mac_work);
- mt76_set(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON);
-
set_bit(MT76_STATE_SUSPEND, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
- bool running, ext_phy = phy != &dev->phy;
+ bool running;
mt7615_mutex_acquire(dev);
ieee80211_queue_delayed_work(hw, &phy->mac_work,
MT7615_WATCHDOG_TIME);
- mt76_clear(dev, MT_WF_RFCR(ext_phy), MT_WF_RFCR_DROP_OTHER_BEACON);
mt7615_mutex_release(dev);
};
int err;
- if (vif->type != NL80211_IFTYPE_STATION ||
- !mt7615_firmware_offload(dev))
- return -ENOTSUPP;
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return 0;
err = mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_BSS_ABORT, &req_hdr,
sizeof(req_hdr), false);
struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
int i;
- mt7615_mcu_set_bss_pm(phy->dev, vif, suspend);
-
mt7615_mcu_set_gtk_rekey(phy->dev, vif, suspend);
mt7615_mcu_set_arp_filter(phy->dev, vif, suspend);
struct ieee80211_vif *monitor_vif;
+ u8 n_beacon_vif;
+
u32 rxfilter;
u32 omac_mask;
void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
struct ieee80211_tx_rate *probe_rate,
struct ieee80211_tx_rate *rates);
-int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable);
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);
int mt7615_init_debugfs(struct mt7615_dev *dev);
int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq);
+int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,
+ struct ieee80211_vif *vif,
+ bool enable);
int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend);