Commit 708d50ed authored by Ayala Beker's avatar Ayala Beker Committed by Johannes Berg

mac80211: add boilerplate code for start / stop NAN

This code doesn't do much besides allowing to start and
stop the vif.
Signed-off-by: default avatarAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarAyala Beker <ayala.beker@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent cb3b7d87
...@@ -3420,6 +3420,9 @@ enum ieee80211_reconfig_type { ...@@ -3420,6 +3420,9 @@ enum ieee80211_reconfig_type {
* synchronization which is needed in case driver has in its RSS queues * synchronization which is needed in case driver has in its RSS queues
* pending frames that were received prior to the control path action * pending frames that were received prior to the control path action
* currently taken (e.g. disassociation) but are not processed yet. * currently taken (e.g. disassociation) but are not processed yet.
*
* @start_nan: join an existing NAN cluster, or create a new one.
* @stop_nan: leave the NAN cluster.
*/ */
struct ieee80211_ops { struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, void (*tx)(struct ieee80211_hw *hw,
...@@ -3655,6 +3658,12 @@ struct ieee80211_ops { ...@@ -3655,6 +3658,12 @@ struct ieee80211_ops {
void (*wake_tx_queue)(struct ieee80211_hw *hw, void (*wake_tx_queue)(struct ieee80211_hw *hw,
struct ieee80211_txq *txq); struct ieee80211_txq *txq);
void (*sync_rx_queues)(struct ieee80211_hw *hw); void (*sync_rx_queues)(struct ieee80211_hw *hw);
int (*start_nan)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_nan_conf *conf);
int (*stop_nan)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
}; };
/** /**
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
* *
* This file is GPLv2 as found in COPYING. * This file is GPLv2 as found in COPYING.
*/ */
...@@ -152,6 +153,39 @@ static void ieee80211_stop_p2p_device(struct wiphy *wiphy, ...@@ -152,6 +153,39 @@ static void ieee80211_stop_p2p_device(struct wiphy *wiphy,
ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev)); ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev));
} }
static int ieee80211_start_nan(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct cfg80211_nan_conf *conf)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
int ret;
mutex_lock(&sdata->local->chanctx_mtx);
ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
mutex_unlock(&sdata->local->chanctx_mtx);
if (ret < 0)
return ret;
ret = ieee80211_do_open(wdev, true);
if (ret)
return ret;
ret = drv_start_nan(sdata->local, sdata, conf);
if (ret)
ieee80211_sdata_stop(sdata);
return ret;
}
static void ieee80211_stop_nan(struct wiphy *wiphy,
struct wireless_dev *wdev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
drv_stop_nan(sdata->local, sdata);
ieee80211_sdata_stop(sdata);
}
static int ieee80211_set_noack_map(struct wiphy *wiphy, static int ieee80211_set_noack_map(struct wiphy *wiphy,
struct net_device *dev, struct net_device *dev,
u16 noack_map) u16 noack_map)
...@@ -3464,4 +3498,6 @@ const struct cfg80211_ops mac80211_config_ops = { ...@@ -3464,4 +3498,6 @@ const struct cfg80211_ops mac80211_config_ops = {
.set_ap_chanwidth = ieee80211_set_ap_chanwidth, .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
.add_tx_ts = ieee80211_add_tx_ts, .add_tx_ts = ieee80211_add_tx_ts,
.del_tx_ts = ieee80211_del_tx_ts, .del_tx_ts = ieee80211_del_tx_ts,
.start_nan = ieee80211_start_nan,
.stop_nan = ieee80211_stop_nan,
}; };
...@@ -647,6 +647,9 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, ...@@ -647,6 +647,9 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
struct ieee80211_chanctx *curr_ctx = NULL; struct ieee80211_chanctx *curr_ctx = NULL;
int ret = 0; int ret = 0;
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
return -ENOTSUPP;
conf = rcu_dereference_protected(sdata->vif.chanctx_conf, conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx)); lockdep_is_held(&local->chanctx_mtx));
......
...@@ -162,6 +162,7 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, ...@@ -162,6 +162,7 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
return; return;
if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
sdata->vif.type == NL80211_IFTYPE_NAN ||
(sdata->vif.type == NL80211_IFTYPE_MONITOR && (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
!sdata->vif.mu_mimo_owner))) !sdata->vif.mu_mimo_owner)))
return; return;
...@@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local, ...@@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
local->ops->wake_tx_queue(&local->hw, &txq->txq); local->ops->wake_tx_queue(&local->hw, &txq->txq);
} }
static inline int drv_start_nan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct cfg80211_nan_conf *conf)
{
int ret;
might_sleep();
check_sdata_in_driver(sdata);
trace_drv_start_nan(local, sdata, conf);
ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
trace_drv_return_int(local, ret);
return ret;
}
static inline void drv_stop_nan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
might_sleep();
check_sdata_in_driver(sdata);
trace_drv_stop_nan(local, sdata);
local->ops->stop_nan(&local->hw, &sdata->vif);
trace_drv_return_void(local);
}
#endif /* __MAC80211_DRIVER_OPS */ #endif /* __MAC80211_DRIVER_OPS */
...@@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata, ...@@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
int n_queues = sdata->local->hw.queues; int n_queues = sdata->local->hw.queues;
int i; int i;
if (iftype == NL80211_IFTYPE_NAN)
return 0;
if (iftype != NL80211_IFTYPE_P2P_DEVICE) { if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
for (i = 0; i < IEEE80211_NUM_ACS; i++) { for (i = 0; i < IEEE80211_NUM_ACS; i++) {
if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
...@@ -647,7 +650,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ...@@ -647,7 +650,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
local->fif_probe_req++; local->fif_probe_req++;
} }
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
sdata->vif.type != NL80211_IFTYPE_NAN)
changed |= ieee80211_reset_erp_info(sdata); changed |= ieee80211_reset_erp_info(sdata);
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
...@@ -1726,7 +1730,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ...@@ -1726,7 +1730,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
ASSERT_RTNL(); ASSERT_RTNL();
if (type == NL80211_IFTYPE_P2P_DEVICE) { if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) {
struct wireless_dev *wdev; struct wireless_dev *wdev;
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size,
......
...@@ -821,6 +821,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -821,6 +821,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
!local->ops->tdls_recv_channel_switch)) !local->ops->tdls_recv_channel_switch))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (WARN_ON(local->hw.wiphy->interface_modes &
BIT(NL80211_IFTYPE_NAN) &&
(!local->ops->start_nan || !local->ops->stop_nan)))
return -EINVAL;
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume)) if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
return -EINVAL; return -EINVAL;
......
...@@ -128,7 +128,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) ...@@ -128,7 +128,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
sdata->vif.type == NL80211_IFTYPE_NAN)
continue; continue;
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
......
...@@ -1700,6 +1700,56 @@ TRACE_EVENT(drv_get_expected_throughput, ...@@ -1700,6 +1700,56 @@ TRACE_EVENT(drv_get_expected_throughput,
) )
); );
TRACE_EVENT(drv_start_nan,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct cfg80211_nan_conf *conf),
TP_ARGS(local, sdata, conf),
TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
__field(u8, master_pref)
__field(u8, dual)
),
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
__entry->master_pref = conf->master_pref;
__entry->dual = conf->dual;
),
TP_printk(
LOCAL_PR_FMT VIF_PR_FMT
", master preference: %u, dual: %d",
LOCAL_PR_ARG, VIF_PR_ARG, __entry->master_pref,
__entry->dual
)
);
TRACE_EVENT(drv_stop_nan,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata),
TP_ARGS(local, sdata),
TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
),
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
),
TP_printk(
LOCAL_PR_FMT VIF_PR_FMT,
LOCAL_PR_ARG, VIF_PR_ARG
)
);
/* /*
* Tracing for API calls that drivers call. * Tracing for API calls that drivers call.
*/ */
......
...@@ -1209,7 +1209,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, ...@@ -1209,7 +1209,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
} }
if (sdata->vif.type != NL80211_IFTYPE_MONITOR && if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
sdata->vif.type != NL80211_IFTYPE_NAN) {
sdata->vif.bss_conf.qos = enable_qos; sdata->vif.bss_conf.qos = enable_qos;
if (bss_notify) if (bss_notify)
ieee80211_bss_info_change_notify(sdata, ieee80211_bss_info_change_notify(sdata,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment