diff options
author | Johannes Berg <johannes.berg@intel.com> | 2018-05-18 03:57:55 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2018-05-18 05:14:35 -0400 |
commit | 73887fd906bb77a974fa02663df9937d0aff053a (patch) | |
tree | 9f2301560feb727cca41cb72fd8848dc302b7392 | |
parent | 8689c051a20195b228e19acb155c7d6e48a86753 (diff) |
cfg80211/mac80211: revert to stack allocation for sinfo
Arend's previous patch made the sinfo structure smaller
again by to dynamically allocating the per-tid stats
only when needed. Thus, revert to stack allocation for
the struct to simplify the code.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/ethtool.c | 32 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 86 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 23 |
3 files changed, 48 insertions, 93 deletions
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c index 09210aa8ea9a..2ba5686cbcab 100644 --- a/net/mac80211/ethtool.c +++ b/net/mac80211/ethtool.c | |||
@@ -71,15 +71,11 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
71 | struct ieee80211_channel *channel; | 71 | struct ieee80211_channel *channel; |
72 | struct sta_info *sta; | 72 | struct sta_info *sta; |
73 | struct ieee80211_local *local = sdata->local; | 73 | struct ieee80211_local *local = sdata->local; |
74 | struct station_info *sinfo; | 74 | struct station_info sinfo; |
75 | struct survey_info survey; | 75 | struct survey_info survey; |
76 | int i, q; | 76 | int i, q; |
77 | #define STA_STATS_SURVEY_LEN 7 | 77 | #define STA_STATS_SURVEY_LEN 7 |
78 | 78 | ||
79 | sinfo = kmalloc(sizeof(*sinfo), GFP_KERNEL); | ||
80 | if (!sinfo) | ||
81 | return; | ||
82 | |||
83 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); | 79 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); |
84 | 80 | ||
85 | #define ADD_STA_STATS(sta) \ | 81 | #define ADD_STA_STATS(sta) \ |
@@ -90,8 +86,8 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
90 | data[i++] += sta->rx_stats.fragments; \ | 86 | data[i++] += sta->rx_stats.fragments; \ |
91 | data[i++] += sta->rx_stats.dropped; \ | 87 | data[i++] += sta->rx_stats.dropped; \ |
92 | \ | 88 | \ |
93 | data[i++] += sinfo->tx_packets; \ | 89 | data[i++] += sinfo.tx_packets; \ |
94 | data[i++] += sinfo->tx_bytes; \ | 90 | data[i++] += sinfo.tx_bytes; \ |
95 | data[i++] += sta->status_stats.filtered; \ | 91 | data[i++] += sta->status_stats.filtered; \ |
96 | data[i++] += sta->status_stats.retry_failed; \ | 92 | data[i++] += sta->status_stats.retry_failed; \ |
97 | data[i++] += sta->status_stats.retry_count; \ | 93 | data[i++] += sta->status_stats.retry_count; \ |
@@ -111,8 +107,8 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
111 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | 107 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) |
112 | goto do_survey; | 108 | goto do_survey; |
113 | 109 | ||
114 | memset(sinfo, 0, sizeof(*sinfo)); | 110 | memset(&sinfo, 0, sizeof(sinfo)); |
115 | sta_set_sinfo(sta, sinfo); | 111 | sta_set_sinfo(sta, &sinfo); |
116 | 112 | ||
117 | i = 0; | 113 | i = 0; |
118 | ADD_STA_STATS(sta); | 114 | ADD_STA_STATS(sta); |
@@ -120,17 +116,17 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
120 | data[i++] = sta->sta_state; | 116 | data[i++] = sta->sta_state; |
121 | 117 | ||
122 | 118 | ||
123 | if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) | 119 | if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) |
124 | data[i] = 100000ULL * | 120 | data[i] = 100000ULL * |
125 | cfg80211_calculate_bitrate(&sinfo->txrate); | 121 | cfg80211_calculate_bitrate(&sinfo.txrate); |
126 | i++; | 122 | i++; |
127 | if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) | 123 | if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE)) |
128 | data[i] = 100000ULL * | 124 | data[i] = 100000ULL * |
129 | cfg80211_calculate_bitrate(&sinfo->rxrate); | 125 | cfg80211_calculate_bitrate(&sinfo.rxrate); |
130 | i++; | 126 | i++; |
131 | 127 | ||
132 | if (sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG)) | 128 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL_AVG)) |
133 | data[i] = (u8)sinfo->signal_avg; | 129 | data[i] = (u8)sinfo.signal_avg; |
134 | i++; | 130 | i++; |
135 | } else { | 131 | } else { |
136 | list_for_each_entry(sta, &local->sta_list, list) { | 132 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -138,16 +134,14 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
138 | if (sta->sdata->dev != dev) | 134 | if (sta->sdata->dev != dev) |
139 | continue; | 135 | continue; |
140 | 136 | ||
141 | memset(sinfo, 0, sizeof(*sinfo)); | 137 | memset(&sinfo, 0, sizeof(sinfo)); |
142 | sta_set_sinfo(sta, sinfo); | 138 | sta_set_sinfo(sta, &sinfo); |
143 | i = 0; | 139 | i = 0; |
144 | ADD_STA_STATS(sta); | 140 | ADD_STA_STATS(sta); |
145 | } | 141 | } |
146 | } | 142 | } |
147 | 143 | ||
148 | do_survey: | 144 | do_survey: |
149 | kfree(sinfo); | ||
150 | |||
151 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; | 145 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; |
152 | /* Get survey stats for current channel */ | 146 | /* Get survey stats for current channel */ |
153 | survey.filled = 0; | 147 | survey.filled = 0; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3d638f11edb5..7daceb1f253d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -4723,17 +4723,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, | |||
4723 | static int nl80211_dump_station(struct sk_buff *skb, | 4723 | static int nl80211_dump_station(struct sk_buff *skb, |
4724 | struct netlink_callback *cb) | 4724 | struct netlink_callback *cb) |
4725 | { | 4725 | { |
4726 | struct station_info *sinfo; | 4726 | struct station_info sinfo; |
4727 | struct cfg80211_registered_device *rdev; | 4727 | struct cfg80211_registered_device *rdev; |
4728 | struct wireless_dev *wdev; | 4728 | struct wireless_dev *wdev; |
4729 | u8 mac_addr[ETH_ALEN]; | 4729 | u8 mac_addr[ETH_ALEN]; |
4730 | int sta_idx = cb->args[2]; | 4730 | int sta_idx = cb->args[2]; |
4731 | int err; | 4731 | int err; |
4732 | 4732 | ||
4733 | sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); | ||
4734 | if (!sinfo) | ||
4735 | return -ENOMEM; | ||
4736 | |||
4737 | rtnl_lock(); | 4733 | rtnl_lock(); |
4738 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 4734 | err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
4739 | if (err) | 4735 | if (err) |
@@ -4750,9 +4746,9 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
4750 | } | 4746 | } |
4751 | 4747 | ||
4752 | while (1) { | 4748 | while (1) { |
4753 | memset(sinfo, 0, sizeof(*sinfo)); | 4749 | memset(&sinfo, 0, sizeof(sinfo)); |
4754 | err = rdev_dump_station(rdev, wdev->netdev, sta_idx, | 4750 | err = rdev_dump_station(rdev, wdev->netdev, sta_idx, |
4755 | mac_addr, sinfo); | 4751 | mac_addr, &sinfo); |
4756 | if (err == -ENOENT) | 4752 | if (err == -ENOENT) |
4757 | break; | 4753 | break; |
4758 | if (err) | 4754 | if (err) |
@@ -4762,7 +4758,7 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
4762 | NETLINK_CB(cb->skb).portid, | 4758 | NETLINK_CB(cb->skb).portid, |
4763 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 4759 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
4764 | rdev, wdev->netdev, mac_addr, | 4760 | rdev, wdev->netdev, mac_addr, |
4765 | sinfo) < 0) | 4761 | &sinfo) < 0) |
4766 | goto out; | 4762 | goto out; |
4767 | 4763 | ||
4768 | sta_idx++; | 4764 | sta_idx++; |
@@ -4773,7 +4769,6 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
4773 | err = skb->len; | 4769 | err = skb->len; |
4774 | out_err: | 4770 | out_err: |
4775 | rtnl_unlock(); | 4771 | rtnl_unlock(); |
4776 | kfree(sinfo); | ||
4777 | 4772 | ||
4778 | return err; | 4773 | return err; |
4779 | } | 4774 | } |
@@ -4782,49 +4777,37 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
4782 | { | 4777 | { |
4783 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4778 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4784 | struct net_device *dev = info->user_ptr[1]; | 4779 | struct net_device *dev = info->user_ptr[1]; |
4785 | struct station_info *sinfo; | 4780 | struct station_info sinfo; |
4786 | struct sk_buff *msg; | 4781 | struct sk_buff *msg; |
4787 | u8 *mac_addr = NULL; | 4782 | u8 *mac_addr = NULL; |
4788 | int err; | 4783 | int err; |
4789 | 4784 | ||
4790 | sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); | 4785 | memset(&sinfo, 0, sizeof(sinfo)); |
4791 | if (!sinfo) | ||
4792 | return -ENOMEM; | ||
4793 | 4786 | ||
4794 | if (!info->attrs[NL80211_ATTR_MAC]) { | 4787 | if (!info->attrs[NL80211_ATTR_MAC]) |
4795 | err = -EINVAL; | 4788 | return -EINVAL; |
4796 | goto out; | ||
4797 | } | ||
4798 | 4789 | ||
4799 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4790 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
4800 | 4791 | ||
4801 | if (!rdev->ops->get_station) { | 4792 | if (!rdev->ops->get_station) |
4802 | err = -EOPNOTSUPP; | 4793 | return -EOPNOTSUPP; |
4803 | goto out; | ||
4804 | } | ||
4805 | 4794 | ||
4806 | err = rdev_get_station(rdev, dev, mac_addr, sinfo); | 4795 | err = rdev_get_station(rdev, dev, mac_addr, &sinfo); |
4807 | if (err) | 4796 | if (err) |
4808 | goto out; | 4797 | return err; |
4809 | 4798 | ||
4810 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4799 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
4811 | if (!msg) { | 4800 | if (!msg) |
4812 | err = -ENOMEM; | 4801 | return -ENOMEM; |
4813 | goto out; | ||
4814 | } | ||
4815 | 4802 | ||
4816 | if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, | 4803 | if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, |
4817 | info->snd_portid, info->snd_seq, 0, | 4804 | info->snd_portid, info->snd_seq, 0, |
4818 | rdev, dev, mac_addr, sinfo) < 0) { | 4805 | rdev, dev, mac_addr, &sinfo) < 0) { |
4819 | nlmsg_free(msg); | 4806 | nlmsg_free(msg); |
4820 | err = -ENOBUFS; | 4807 | return -ENOBUFS; |
4821 | goto out; | ||
4822 | } | 4808 | } |
4823 | 4809 | ||
4824 | err = genlmsg_reply(msg, info); | 4810 | return genlmsg_reply(msg, info); |
4825 | out: | ||
4826 | kfree(sinfo); | ||
4827 | return err; | ||
4828 | } | 4811 | } |
4829 | 4812 | ||
4830 | int cfg80211_check_station_change(struct wiphy *wiphy, | 4813 | int cfg80211_check_station_change(struct wiphy *wiphy, |
@@ -10088,26 +10071,18 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, | |||
10088 | */ | 10071 | */ |
10089 | if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss && | 10072 | if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss && |
10090 | rdev->ops->get_station) { | 10073 | rdev->ops->get_station) { |
10091 | struct station_info *sinfo; | 10074 | struct station_info sinfo = {}; |
10092 | u8 *mac_addr; | 10075 | u8 *mac_addr; |
10093 | 10076 | ||
10094 | sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); | ||
10095 | if (!sinfo) | ||
10096 | return -ENOMEM; | ||
10097 | |||
10098 | mac_addr = wdev->current_bss->pub.bssid; | 10077 | mac_addr = wdev->current_bss->pub.bssid; |
10099 | 10078 | ||
10100 | err = rdev_get_station(rdev, dev, mac_addr, sinfo); | 10079 | err = rdev_get_station(rdev, dev, mac_addr, &sinfo); |
10101 | if (err) { | 10080 | if (err) |
10102 | kfree(sinfo); | ||
10103 | return err; | 10081 | return err; |
10104 | } | ||
10105 | 10082 | ||
10106 | if (sinfo->filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) | 10083 | if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) |
10107 | wdev->cqm_config->last_rssi_event_value = | 10084 | wdev->cqm_config->last_rssi_event_value = |
10108 | (s8)sinfo->rx_beacon_signal_avg; | 10085 | (s8) sinfo.rx_beacon_signal_avg; |
10109 | |||
10110 | kfree(sinfo); | ||
10111 | } | 10086 | } |
10112 | 10087 | ||
10113 | last = wdev->cqm_config->last_rssi_event_value; | 10088 | last = wdev->cqm_config->last_rssi_event_value; |
@@ -14641,32 +14616,25 @@ void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr, | |||
14641 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | 14616 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; |
14642 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 14617 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
14643 | struct sk_buff *msg; | 14618 | struct sk_buff *msg; |
14644 | struct station_info *empty_sinfo = NULL; | 14619 | struct station_info empty_sinfo = {}; |
14645 | 14620 | ||
14646 | if (!sinfo) { | 14621 | if (!sinfo) |
14647 | empty_sinfo = kzalloc(sizeof(*empty_sinfo), GFP_KERNEL); | 14622 | sinfo = &empty_sinfo; |
14648 | if (!empty_sinfo) | ||
14649 | return; | ||
14650 | sinfo = empty_sinfo; | ||
14651 | } | ||
14652 | 14623 | ||
14653 | trace_cfg80211_del_sta(dev, mac_addr); | 14624 | trace_cfg80211_del_sta(dev, mac_addr); |
14654 | 14625 | ||
14655 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 14626 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
14656 | if (!msg) | 14627 | if (!msg) |
14657 | goto out; | 14628 | return; |
14658 | 14629 | ||
14659 | if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0, | 14630 | if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0, |
14660 | rdev, dev, mac_addr, sinfo) < 0) { | 14631 | rdev, dev, mac_addr, sinfo) < 0) { |
14661 | nlmsg_free(msg); | 14632 | nlmsg_free(msg); |
14662 | goto out; | 14633 | return; |
14663 | } | 14634 | } |
14664 | 14635 | ||
14665 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 14636 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, |
14666 | NL80211_MCGRP_MLME, gfp); | 14637 | NL80211_MCGRP_MLME, gfp); |
14667 | |||
14668 | out: | ||
14669 | kfree(empty_sinfo); | ||
14670 | } | 14638 | } |
14671 | EXPORT_SYMBOL(cfg80211_del_sta_sinfo); | 14639 | EXPORT_SYMBOL(cfg80211_del_sta_sinfo); |
14672 | 14640 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 9e002df0f8d8..05186a47878f 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1254,7 +1254,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev, | |||
1254 | { | 1254 | { |
1255 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1255 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1256 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 1256 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
1257 | struct station_info *sinfo; | 1257 | struct station_info sinfo = {}; |
1258 | u8 addr[ETH_ALEN]; | 1258 | u8 addr[ETH_ALEN]; |
1259 | int err; | 1259 | int err; |
1260 | 1260 | ||
@@ -1274,23 +1274,16 @@ static int cfg80211_wext_giwrate(struct net_device *dev, | |||
1274 | if (err) | 1274 | if (err) |
1275 | return err; | 1275 | return err; |
1276 | 1276 | ||
1277 | sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); | 1277 | err = rdev_get_station(rdev, dev, addr, &sinfo); |
1278 | if (!sinfo) | ||
1279 | return -ENOMEM; | ||
1280 | |||
1281 | err = rdev_get_station(rdev, dev, addr, sinfo); | ||
1282 | if (err) | 1278 | if (err) |
1283 | goto out; | 1279 | return err; |
1284 | 1280 | ||
1285 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) { | 1281 | if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))) |
1286 | err = -EOPNOTSUPP; | 1282 | return -EOPNOTSUPP; |
1287 | goto out; | ||
1288 | } | ||
1289 | 1283 | ||
1290 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo->txrate); | 1284 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); |
1291 | out: | 1285 | |
1292 | kfree(sinfo); | 1286 | return 0; |
1293 | return err; | ||
1294 | } | 1287 | } |
1295 | 1288 | ||
1296 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ | 1289 | /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ |