From: Assaf Krauss <assaf.krauss@xxxxxxxxx> Add support for requesting an FTM (Fine Timing Measurement), receiving a notification with its results, and aborting it. There's no actual implementation as it depends entirely on low-level device/driver support. Signed-off-by: Assaf Krauss <assaf.krauss@xxxxxxxxx> Signed-off-by: Beni Lev <beni.lev@xxxxxxxxx> Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> --- include/net/mac80211.h | 10 +++++++++ net/mac80211/cfg.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 4 +++- net/mac80211/main.c | 3 +++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7c30faff245f..52c6ea752a4a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3269,6 +3269,11 @@ enum ieee80211_reconfig_type { * the function call. * * @wake_tx_queue: Called when new packets have been added to the queue. + * + * @perform_ftm: Perform a Fine Timing Measurement with the given request + * parameters. The given request can only be used within the function call. + * @abort_ftm: Abort a Fine Timing Measurement request. The given cookie must + * match that of the active FTM request. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -3508,6 +3513,11 @@ struct ieee80211_ops { void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq); + + int (*perform_ftm)(struct ieee80211_hw *hw, u64 cookie, + struct ieee80211_vif *vif, + struct cfg80211_ftm_request *ftm_req); + int (*abort_ftm)(struct ieee80211_hw *hw, u64 cookie); }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2d1c4c35186d..2afaa761cb16 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3322,6 +3322,60 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; } +static u64 ieee80211_msrment_cookie(struct ieee80211_local *local, + enum nl80211_msrment_type type) +{ + ASSERT_RTNL(); + + local->msrment_cookie_counter++; + if (local->msrment_cookie_counter == (1ULL << 48)) + local->msrment_cookie_counter = 1; + + return ((u64)type << 48) | local->msrment_cookie_counter; +} + +static int ieee80211_perform_msrment(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_msrment_request *request, + u64 *cookie) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_vif *vif = wdev_to_ieee80211_vif(wdev); + + *cookie = ieee80211_msrment_cookie(local, request->type); + + switch (request->type) { + case NL80211_MSRMENT_TYPE_FTM: + if (!local->ops->perform_ftm) + return -EOPNOTSUPP; + return local->ops->perform_ftm(&local->hw, *cookie, vif, + &request->u.ftm); + default: + break; + } + + return -EOPNOTSUPP; +} + +static int ieee80211_abort_msrment(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + enum nl80211_msrment_type type = cookie >> 48; + + switch (type) { + case NL80211_MSRMENT_TYPE_FTM: + if (!local->ops->abort_ftm) + return -EOPNOTSUPP; + return local->ops->abort_ftm(&local->hw, cookie); + default: + break; + } + + return -EOPNOTSUPP; +} + const struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -3342,6 +3396,8 @@ const struct cfg80211_ops mac80211_config_ops = { .get_station = ieee80211_get_station, .dump_station = ieee80211_dump_station, .dump_survey = ieee80211_dump_survey, + .perform_msrment = ieee80211_perform_msrment, + .abort_msrment = ieee80211_abort_msrment, #ifdef CONFIG_MAC80211_MESH .add_mpath = ieee80211_add_mpath, .del_mpath = ieee80211_del_mpath, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c30b6842ed9f..294aec41fca7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1347,11 +1347,13 @@ struct ieee80211_local { struct cfg80211_chan_def monitor_chandef; /* extended capabilities provided by mac80211 */ - u8 ext_capa[8]; + u8 ext_capa[9]; /* TDLS channel switch */ struct work_struct tdls_chsw_work; struct sk_buff_head skb_queue_tdls_chsw; + + u64 msrment_cookie_counter; }; static inline struct ieee80211_sub_if_data * diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6bcf0faa4a89..b7fbcecd40ef 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1006,6 +1006,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA)) local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING; + if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_FTM_INITIATOR) + local->ext_capa[8] |= WLAN_EXT_CAPA9_FTM_INITIATOR; + local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM; result = wiphy_register(local->hw.wiphy); -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html