Not much for -next so far, but here it goes:
* send more nl80211 events for interfaces * remove useless network/transport offset mangling code * validate beacon intervals identically for all interface types * use driver rate estimates for mesh * fix a compiler type/signedness warning -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJXrZSMAAoJEGt7eEactAAd3kAP/1zUHvAZ3qDaz9zz08cIL35R CXXDtaFip6k4q78ZU1OLKBbR6VXlxZ8mplQ15xtU5Cx7KIzJMG1pWMDpmuvOSttB 4pyg+43CDYSWP9gdxS8jYZVx+KL8+SzrIs4ygvfZv8B5ATSLcTbOGUBlxSylY9FP CK35I9bL68girl6INb12NtkUwDiA6iC/n9i/62ao/2ywOXEljkwx+JNnk3aiT7Uj PBRPHY1lK9AynpNyJjpB9Mwip0HNnbS0Ay8WLpPsqQ8NlWH60tEcpEf4L0pBB8cU l5vs9y6TX/9V9OiVPXHgHjPJ2B3XzCY6DbqE1X5jlzFO1hc9o6y1vh8lqE4PXY/J brN6nwXObPnx3PDiiqxU33oiXvoQvo8JjBllA3isD2tbseSNZBLewbtdpLOdXtsS eaY8WyPaLvEfZjI8KJaQn2GvzPzXWLKHdxpYZtxavK0ss7OYioexS13qYxu+i2Tu 8QHOqymI0rfEuyTqOKWxpbUmu4xRyH3Gn6WxOFa/tY4BSKNLfUH7EHvnbh+aX1Hp IGDTc3erD43agPcn2wYpQtFJ6k9oRIyIakKicP66l4kQrIItfUm6jPIHhYA2D9F4 SrToRZRoVFFOYQEzPoQ0ZEXBYXXa1x8DxoghX50hzX89cqRlFT0jvZHJxlSCLg+h OzfMU4jtWCwRSK0N2EZ5 =C5wa -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2016-08-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== Not much for -next so far, but here it goes: * send more nl80211 events for interfaces * remove useless network/transport offset mangling code * validate beacon intervals identically for all interface types * use driver rate estimates for mesh * fix a compiler type/signedness warning ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
5f3b9d3654
|
@ -1088,13 +1088,13 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
|
||||
struct ieee80211_sta *sta)
|
||||
struct sta_info *sta)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
trace_drv_get_expected_throughput(sta);
|
||||
if (local->ops->get_expected_throughput)
|
||||
ret = local->ops->get_expected_throughput(&local->hw, sta);
|
||||
trace_drv_get_expected_throughput(&sta->sta);
|
||||
if (local->ops->get_expected_throughput && sta->uploaded)
|
||||
ret = local->ops->get_expected_throughput(&local->hw, &sta->sta);
|
||||
trace_drv_return_u32(local, ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -326,22 +326,33 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
|
|||
u32 tx_time, estimated_retx;
|
||||
u64 result;
|
||||
|
||||
if (sta->mesh->fail_avg >= 100)
|
||||
return MAX_METRIC;
|
||||
/* Try to get rate based on HW/SW RC algorithm.
|
||||
* Rate is returned in units of Kbps, correct this
|
||||
* to comply with airtime calculation units
|
||||
* Round up in case we get rate < 100Kbps
|
||||
*/
|
||||
rate = DIV_ROUND_UP(sta_get_expected_throughput(sta), 100);
|
||||
|
||||
sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
|
||||
rate = cfg80211_calculate_bitrate(&rinfo);
|
||||
if (WARN_ON(!rate))
|
||||
return MAX_METRIC;
|
||||
if (rate) {
|
||||
err = 0;
|
||||
} else {
|
||||
if (sta->mesh->fail_avg >= 100)
|
||||
return MAX_METRIC;
|
||||
|
||||
err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
|
||||
sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
|
||||
rate = cfg80211_calculate_bitrate(&rinfo);
|
||||
if (WARN_ON(!rate))
|
||||
return MAX_METRIC;
|
||||
|
||||
err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
|
||||
}
|
||||
|
||||
/* bitrate is in units of 100 Kbps, while we need rate in units of
|
||||
* 1Mbps. This will be corrected on tx_time computation.
|
||||
*/
|
||||
tx_time = (device_constant + 10 * test_frame_len / rate);
|
||||
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
|
||||
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
|
||||
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
|
||||
return (u32)result;
|
||||
}
|
||||
|
||||
|
|
|
@ -2279,11 +2279,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
||||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
|
||||
/* check if the driver has a SW RC implementation */
|
||||
if (ref && ref->ops->get_expected_throughput)
|
||||
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
|
||||
else
|
||||
thr = drv_get_expected_throughput(local, &sta->sta);
|
||||
thr = sta_get_expected_throughput(sta);
|
||||
|
||||
if (thr != 0) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
|
||||
|
@ -2291,6 +2287,25 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
}
|
||||
}
|
||||
|
||||
u32 sta_get_expected_throughput(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct rate_control_ref *ref = NULL;
|
||||
u32 thr = 0;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
|
||||
ref = local->rate_ctrl;
|
||||
|
||||
/* check if the driver has a SW RC implementation */
|
||||
if (ref && ref->ops->get_expected_throughput)
|
||||
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
|
||||
else
|
||||
thr = drv_get_expected_throughput(local, sta);
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
unsigned long ieee80211_sta_last_active(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
|
||||
|
|
|
@ -712,6 +712,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
|
|||
struct rate_info *rinfo);
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
|
||||
|
||||
u32 sta_get_expected_throughput(struct sta_info *sta);
|
||||
|
||||
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
|
||||
unsigned long exp_time);
|
||||
u8 sta_info_tx_streams(struct sta_info *sta);
|
||||
|
|
|
@ -2334,7 +2334,6 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
|
|||
struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;
|
||||
const u8 *encaps_data;
|
||||
int encaps_len, skip_header_bytes;
|
||||
int nh_pos, h_pos;
|
||||
bool wme_sta = false, authorized = false;
|
||||
bool tdls_peer;
|
||||
bool multicast;
|
||||
|
@ -2640,13 +2639,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
|
|||
encaps_len = 0;
|
||||
}
|
||||
|
||||
nh_pos = skb_network_header(skb) - skb->data;
|
||||
h_pos = skb_transport_header(skb) - skb->data;
|
||||
|
||||
skb_pull(skb, skip_header_bytes);
|
||||
nh_pos -= skip_header_bytes;
|
||||
h_pos -= skip_header_bytes;
|
||||
|
||||
head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
|
||||
|
||||
/*
|
||||
|
@ -2672,18 +2665,12 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
}
|
||||
|
||||
if (encaps_data) {
|
||||
if (encaps_data)
|
||||
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
|
||||
nh_pos += encaps_len;
|
||||
h_pos += encaps_len;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (meshhdrlen > 0) {
|
||||
if (meshhdrlen > 0)
|
||||
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
|
||||
nh_pos += meshhdrlen;
|
||||
h_pos += meshhdrlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
|
@ -2699,15 +2686,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
|
|||
} else
|
||||
memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
|
||||
|
||||
nh_pos += hdrlen;
|
||||
h_pos += hdrlen;
|
||||
|
||||
/* Update skb pointers to various headers since this modified frame
|
||||
* is going to go through Linux networking code that may potentially
|
||||
* need things like pointer to IP header. */
|
||||
skb_reset_mac_header(skb);
|
||||
skb_set_network_header(skb, nh_pos);
|
||||
skb_set_transport_header(skb, h_pos);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
@ -4390,9 +4369,6 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
|
|||
int ac = ieee802_1d_to_ac[tid & 7];
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
skb_set_queue_mapping(skb, ac);
|
||||
skb->priority = tid;
|
||||
|
||||
|
|
|
@ -906,6 +906,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|||
if (WARN_ON(wdev->netdev))
|
||||
return;
|
||||
|
||||
nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
|
||||
|
||||
list_del_rcu(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
|
||||
|
@ -1079,6 +1081,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
|
||||
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
|
||||
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
cfg80211_leave(rdev, wdev);
|
||||
|
@ -1157,6 +1161,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
* remove and clean it up.
|
||||
*/
|
||||
if (!list_empty(&wdev->list)) {
|
||||
nl80211_notify_iface(rdev, wdev,
|
||||
NL80211_CMD_DEL_INTERFACE);
|
||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_rcu(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
|
|
|
@ -2751,7 +2751,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct vif_params params;
|
||||
struct wireless_dev *wdev;
|
||||
struct sk_buff *msg, *event;
|
||||
struct sk_buff *msg;
|
||||
int err;
|
||||
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
|
||||
u32 flags;
|
||||
|
@ -2855,20 +2855,15 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (event) {
|
||||
if (nl80211_send_iface(event, 0, 0, 0,
|
||||
rdev, wdev, false) < 0) {
|
||||
nlmsg_free(event);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* For wdevs which have no associated netdev object (e.g. of type
|
||||
* NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
|
||||
* For all other types, the event will be generated from the
|
||||
* netdev notifier
|
||||
*/
|
||||
if (!wdev->netdev)
|
||||
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
|
||||
event, 0, NL80211_MCGRP_CONFIG,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
out:
|
||||
return genlmsg_reply(msg, info);
|
||||
}
|
||||
|
||||
|
@ -2876,18 +2871,10 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct wireless_dev *wdev = info->user_ptr[1];
|
||||
struct sk_buff *msg;
|
||||
int status;
|
||||
|
||||
if (!rdev->ops->del_virtual_intf)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
|
||||
nlmsg_free(msg);
|
||||
msg = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we remove a wireless device without a netdev then clear
|
||||
* user_ptr[1] so that nl80211_post_doit won't dereference it
|
||||
|
@ -2898,15 +2885,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!wdev->netdev)
|
||||
info->user_ptr[1] = NULL;
|
||||
|
||||
status = rdev_del_virtual_intf(rdev, wdev);
|
||||
if (status >= 0 && msg)
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
|
||||
msg, 0, NL80211_MCGRP_CONFIG,
|
||||
GFP_KERNEL);
|
||||
else
|
||||
nlmsg_free(msg);
|
||||
|
||||
return status;
|
||||
return rdev_del_virtual_intf(rdev, wdev);
|
||||
}
|
||||
|
||||
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
|
||||
|
@ -5374,6 +5353,18 @@ static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *ou
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_check_power_mode(const struct nlattr *nla,
|
||||
enum nl80211_mesh_power_mode min,
|
||||
enum nl80211_mesh_power_mode max,
|
||||
enum nl80211_mesh_power_mode *out)
|
||||
{
|
||||
u32 val = nla_get_u32(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_parse_mesh_config(struct genl_info *info,
|
||||
struct mesh_config *cfg,
|
||||
u32 *mask_out)
|
||||
|
@ -5518,7 +5509,7 @@ do { \
|
|||
NL80211_MESH_POWER_ACTIVE,
|
||||
NL80211_MESH_POWER_MAX,
|
||||
mask, NL80211_MESHCONF_POWER_MODE,
|
||||
nl80211_check_u32);
|
||||
nl80211_check_power_mode);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
|
||||
0, 65535, mask,
|
||||
NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
|
||||
|
@ -7773,12 +7764,13 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
ibss.beacon_interval = 100;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
|
||||
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
|
||||
ibss.beacon_interval =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
|
||||
if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!rdev->ops->join_ibss)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -9252,9 +9244,10 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
|
||||
setup.beacon_interval =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
|
||||
if (setup.beacon_interval < 10 ||
|
||||
setup.beacon_interval > 10000)
|
||||
return -EINVAL;
|
||||
|
||||
err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
|
||||
|
@ -11847,6 +11840,29 @@ void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
|
|||
NL80211_MCGRP_CONFIG, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
enum nl80211_commands cmd)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
|
||||
WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE &&
|
||||
cmd != NL80211_CMD_DEL_INTERFACE);
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
if (nl80211_send_iface(msg, 0, 0, 0, rdev, wdev,
|
||||
cmd == NL80211_CMD_DEL_INTERFACE) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
|
||||
NL80211_MCGRP_CONFIG, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static int nl80211_add_scan_req(struct sk_buff *msg,
|
||||
struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,9 @@ int nl80211_init(void);
|
|||
void nl80211_exit(void);
|
||||
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_commands cmd);
|
||||
void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
enum nl80211_commands cmd);
|
||||
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
|
||||
|
|
|
@ -1559,7 +1559,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev;
|
||||
int res = 0;
|
||||
|
||||
if (!beacon_int)
|
||||
if (beacon_int < 10 || beacon_int > 10000)
|
||||
return -EINVAL;
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче