aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c82
1 files changed, 27 insertions, 55 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7d737071dedb..b732e219b107 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1618,68 +1618,24 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
1618} 1618}
1619EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); 1619EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
1620 1620
1621static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, 1621void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
1622 enum ieee80211_smps_mode *smps_mode)
1623{ 1622{
1624 if (ifmgd->associated) { 1623 struct ieee80211_local *local = sdata->local;
1625 *smps_mode = ifmgd->ap_smps; 1624 struct ieee80211_chanctx_conf *chanctx_conf;
1626 1625 struct ieee80211_chanctx *chanctx;
1627 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1628 if (ifmgd->powersave)
1629 *smps_mode = IEEE80211_SMPS_DYNAMIC;
1630 else
1631 *smps_mode = IEEE80211_SMPS_OFF;
1632 }
1633
1634 return 1;
1635 }
1636
1637 return 0;
1638}
1639
1640void ieee80211_recalc_smps(struct ieee80211_local *local)
1641{
1642 struct ieee80211_sub_if_data *sdata;
1643 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1644 int count = 0;
1645
1646 mutex_lock(&local->iflist_mtx);
1647
1648 /*
1649 * This function could be improved to handle multiple
1650 * interfaces better, but right now it makes any
1651 * non-station interfaces force SM PS to be turned
1652 * off. If there are multiple station interfaces it
1653 * could also use the best possible mode, e.g. if
1654 * one is in static and the other in dynamic then
1655 * dynamic is ok.
1656 */
1657
1658 list_for_each_entry(sdata, &local->interfaces, list) {
1659 if (!ieee80211_sdata_running(sdata))
1660 continue;
1661 if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
1662 continue;
1663 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1664 goto set;
1665 1626
1666 count += check_mgd_smps(&sdata->u.mgd, &smps_mode); 1627 mutex_lock(&local->chanctx_mtx);
1667 1628
1668 if (count > 1) { 1629 chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1669 smps_mode = IEEE80211_SMPS_OFF; 1630 lockdep_is_held(&local->chanctx_mtx));
1670 break;
1671 }
1672 }
1673 1631
1674 if (smps_mode == local->smps_mode) 1632 if (WARN_ON_ONCE(!chanctx_conf))
1675 goto unlock; 1633 goto unlock;
1676 1634
1677 set: 1635 chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
1678 local->smps_mode = smps_mode; 1636 ieee80211_recalc_smps_chanctx(local, chanctx);
1679 /* changed flag is auto-detected for this */
1680 ieee80211_hw_config(local, 0);
1681 unlock: 1637 unlock:
1682 mutex_unlock(&local->iflist_mtx); 1638 mutex_unlock(&local->chanctx_mtx);
1683} 1639}
1684 1640
1685static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) 1641static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
@@ -1978,3 +1934,19 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif)
1978 return ifmgd->ave_beacon_signal; 1934 return ifmgd->ave_beacon_signal;
1979} 1935}
1980EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); 1936EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
1937
1938u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs)
1939{
1940 if (!mcs)
1941 return 1;
1942
1943 /* TODO: consider rx_highest */
1944
1945 if (mcs->rx_mask[3])
1946 return 4;
1947 if (mcs->rx_mask[2])
1948 return 3;
1949 if (mcs->rx_mask[1])
1950 return 2;
1951 return 1;
1952}