Skip to content

Commit 167e33f

Browse files
AyalaBkrjmberg-intel
authored andcommitted
mac80211: Implement add_nan_func and rm_nan_func
Implement add/rm_nan_func functions and handle NAN function termination notifications. Handle instance_id allocation for NAN functions and implement the reconfig flow. Signed-off-by: Andrei Otcheretianski <[email protected]> Signed-off-by: Emmanuel Grumbach <[email protected]> Signed-off-by: Luca Coelho <[email protected]> Signed-off-by: Johannes Berg <[email protected]>
1 parent 5953ff6 commit 167e33f

File tree

8 files changed

+304
-3
lines changed

8 files changed

+304
-3
lines changed

include/net/mac80211.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,6 +2177,8 @@ enum ieee80211_hw_flags {
21772177
* @n_cipher_schemes: a size of an array of cipher schemes definitions.
21782178
* @cipher_schemes: a pointer to an array of cipher scheme definitions
21792179
* supported by HW.
2180+
* @max_nan_de_entries: maximum number of NAN DE functions supported by the
2181+
* device.
21802182
*/
21812183
struct ieee80211_hw {
21822184
struct ieee80211_conf conf;
@@ -2211,6 +2213,7 @@ struct ieee80211_hw {
22112213
u8 uapsd_max_sp_len;
22122214
u8 n_cipher_schemes;
22132215
const struct ieee80211_cipher_scheme *cipher_schemes;
2216+
u8 max_nan_de_entries;
22142217
};
22152218

22162219
static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
@@ -3429,6 +3432,12 @@ enum ieee80211_reconfig_type {
34293432
* The driver gets both full configuration and the changed parameters since
34303433
* some devices may need the full configuration while others need only the
34313434
* changed parameters.
3435+
* @add_nan_func: Add a NAN function. Returns 0 on success. The data in
3436+
* cfg80211_nan_func must not be referenced outside the scope of
3437+
* this call.
3438+
* @del_nan_func: Remove a NAN function. The driver must call
3439+
* ieee80211_nan_func_terminated() with
3440+
* NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal.
34323441
*/
34333442
struct ieee80211_ops {
34343443
void (*tx)(struct ieee80211_hw *hw,
@@ -3673,6 +3682,12 @@ struct ieee80211_ops {
36733682
int (*nan_change_conf)(struct ieee80211_hw *hw,
36743683
struct ieee80211_vif *vif,
36753684
struct cfg80211_nan_conf *conf, u32 changes);
3685+
int (*add_nan_func)(struct ieee80211_hw *hw,
3686+
struct ieee80211_vif *vif,
3687+
const struct cfg80211_nan_func *nan_func);
3688+
void (*del_nan_func)(struct ieee80211_hw *hw,
3689+
struct ieee80211_vif *vif,
3690+
u8 instance_id);
36763691
};
36773692

36783693
/**
@@ -5746,4 +5761,20 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
57465761
void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
57475762
unsigned long *frame_cnt,
57485763
unsigned long *byte_cnt);
5764+
5765+
/**
5766+
* ieee80211_nan_func_terminated - notify about NAN function termination.
5767+
*
5768+
* This function is used to notify mac80211 about NAN function termination.
5769+
* Note that this function can't be called from hard irq.
5770+
*
5771+
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
5772+
* @inst_id: the local instance id
5773+
* @reason: termination reason (one of the NL80211_NAN_FUNC_TERM_REASON_*)
5774+
* @gfp: allocation flags
5775+
*/
5776+
void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
5777+
u8 inst_id,
5778+
enum nl80211_nan_func_term_reason reason,
5779+
gfp_t gfp);
57495780
#endif /* MAC80211_H */

net/mac80211/cfg.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ static int ieee80211_start_nan(struct wiphy *wiphy,
174174
if (ret)
175175
ieee80211_sdata_stop(sdata);
176176

177+
sdata->u.nan.conf = *conf;
178+
177179
return ret;
178180
}
179181

@@ -216,6 +218,84 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy,
216218
return ret;
217219
}
218220

221+
static int ieee80211_add_nan_func(struct wiphy *wiphy,
222+
struct wireless_dev *wdev,
223+
struct cfg80211_nan_func *nan_func)
224+
{
225+
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
226+
int ret;
227+
228+
if (sdata->vif.type != NL80211_IFTYPE_NAN)
229+
return -EOPNOTSUPP;
230+
231+
if (!ieee80211_sdata_running(sdata))
232+
return -ENETDOWN;
233+
234+
spin_lock_bh(&sdata->u.nan.func_lock);
235+
236+
ret = idr_alloc(&sdata->u.nan.function_inst_ids,
237+
nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
238+
GFP_ATOMIC);
239+
spin_unlock_bh(&sdata->u.nan.func_lock);
240+
241+
if (ret < 0)
242+
return ret;
243+
244+
nan_func->instance_id = ret;
245+
246+
WARN_ON(nan_func->instance_id == 0);
247+
248+
ret = drv_add_nan_func(sdata->local, sdata, nan_func);
249+
if (ret) {
250+
spin_lock_bh(&sdata->u.nan.func_lock);
251+
idr_remove(&sdata->u.nan.function_inst_ids,
252+
nan_func->instance_id);
253+
spin_unlock_bh(&sdata->u.nan.func_lock);
254+
}
255+
256+
return ret;
257+
}
258+
259+
static struct cfg80211_nan_func *
260+
ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
261+
u64 cookie)
262+
{
263+
struct cfg80211_nan_func *func;
264+
int id;
265+
266+
lockdep_assert_held(&sdata->u.nan.func_lock);
267+
268+
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
269+
if (func->cookie == cookie)
270+
return func;
271+
}
272+
273+
return NULL;
274+
}
275+
276+
static void ieee80211_del_nan_func(struct wiphy *wiphy,
277+
struct wireless_dev *wdev, u64 cookie)
278+
{
279+
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
280+
struct cfg80211_nan_func *func;
281+
u8 instance_id = 0;
282+
283+
if (sdata->vif.type != NL80211_IFTYPE_NAN ||
284+
!ieee80211_sdata_running(sdata))
285+
return;
286+
287+
spin_lock_bh(&sdata->u.nan.func_lock);
288+
289+
func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
290+
if (func)
291+
instance_id = func->instance_id;
292+
293+
spin_unlock_bh(&sdata->u.nan.func_lock);
294+
295+
if (instance_id)
296+
drv_del_nan_func(sdata->local, sdata, instance_id);
297+
}
298+
219299
static int ieee80211_set_noack_map(struct wiphy *wiphy,
220300
struct net_device *dev,
221301
u16 noack_map)
@@ -3443,6 +3523,38 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
34433523
return -ENOENT;
34443524
}
34453525

3526+
void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
3527+
u8 inst_id,
3528+
enum nl80211_nan_func_term_reason reason,
3529+
gfp_t gfp)
3530+
{
3531+
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
3532+
struct cfg80211_nan_func *func;
3533+
u64 cookie;
3534+
3535+
if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
3536+
return;
3537+
3538+
spin_lock_bh(&sdata->u.nan.func_lock);
3539+
3540+
func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
3541+
if (WARN_ON(!func)) {
3542+
spin_unlock_bh(&sdata->u.nan.func_lock);
3543+
return;
3544+
}
3545+
3546+
cookie = func->cookie;
3547+
idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
3548+
3549+
spin_unlock_bh(&sdata->u.nan.func_lock);
3550+
3551+
cfg80211_free_nan_func(func);
3552+
3553+
cfg80211_nan_func_terminated(ieee80211_vif_to_wdev(vif), inst_id,
3554+
reason, cookie, gfp);
3555+
}
3556+
EXPORT_SYMBOL(ieee80211_nan_func_terminated);
3557+
34463558
const struct cfg80211_ops mac80211_config_ops = {
34473559
.add_virtual_intf = ieee80211_add_iface,
34483560
.del_virtual_intf = ieee80211_del_iface,
@@ -3531,4 +3643,6 @@ const struct cfg80211_ops mac80211_config_ops = {
35313643
.start_nan = ieee80211_start_nan,
35323644
.stop_nan = ieee80211_stop_nan,
35333645
.nan_change_conf = ieee80211_nan_change_conf,
3646+
.add_nan_func = ieee80211_add_nan_func,
3647+
.del_nan_func = ieee80211_del_nan_func,
35343648
};

net/mac80211/driver-ops.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,4 +1213,36 @@ static inline int drv_nan_change_conf(struct ieee80211_local *local,
12131213
return ret;
12141214
}
12151215

1216+
static inline int drv_add_nan_func(struct ieee80211_local *local,
1217+
struct ieee80211_sub_if_data *sdata,
1218+
const struct cfg80211_nan_func *nan_func)
1219+
{
1220+
int ret;
1221+
1222+
might_sleep();
1223+
check_sdata_in_driver(sdata);
1224+
1225+
if (!local->ops->add_nan_func)
1226+
return -EOPNOTSUPP;
1227+
1228+
trace_drv_add_nan_func(local, sdata, nan_func);
1229+
ret = local->ops->add_nan_func(&local->hw, &sdata->vif, nan_func);
1230+
trace_drv_return_int(local, ret);
1231+
1232+
return ret;
1233+
}
1234+
1235+
static inline void drv_del_nan_func(struct ieee80211_local *local,
1236+
struct ieee80211_sub_if_data *sdata,
1237+
u8 instance_id)
1238+
{
1239+
might_sleep();
1240+
check_sdata_in_driver(sdata);
1241+
1242+
trace_drv_del_nan_func(local, sdata, instance_id);
1243+
if (local->ops->del_nan_func)
1244+
local->ops->del_nan_func(&local->hw, &sdata->vif, instance_id);
1245+
trace_drv_return_void(local);
1246+
}
1247+
12161248
#endif /* __MAC80211_DRIVER_OPS */

net/mac80211/ieee80211_i.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ struct ieee80211_local;
8686

8787
#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */)
8888

89+
#define IEEE80211_MAX_NAN_INSTANCE_ID 255
90+
8991
struct ieee80211_fragment_entry {
9092
struct sk_buff_head skb_list;
9193
unsigned long first_frag_time;
@@ -834,9 +836,14 @@ struct ieee80211_if_mntr {
834836
* struct ieee80211_if_nan - NAN state
835837
*
836838
* @conf: current NAN configuration
839+
* @func_ids: a bitmap of available instance_id's
837840
*/
838841
struct ieee80211_if_nan {
839842
struct cfg80211_nan_conf conf;
843+
844+
/* protects function_inst_ids */
845+
spinlock_t func_lock;
846+
struct idr function_inst_ids;
840847
};
841848

842849
struct ieee80211_sub_if_data {

net/mac80211/iface.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
798798
struct ps_data *ps;
799799
struct cfg80211_chan_def chandef;
800800
bool cancel_scan;
801+
struct cfg80211_nan_func *func;
801802

802803
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
803804

@@ -950,11 +951,22 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
950951

951952
ieee80211_adjust_monitor_flags(sdata, -1);
952953
break;
954+
case NL80211_IFTYPE_NAN:
955+
/* clean all the functions */
956+
spin_lock_bh(&sdata->u.nan.func_lock);
957+
958+
idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
959+
idr_remove(&sdata->u.nan.function_inst_ids, i);
960+
cfg80211_free_nan_func(func);
961+
}
962+
idr_destroy(&sdata->u.nan.function_inst_ids);
963+
964+
spin_unlock_bh(&sdata->u.nan.func_lock);
965+
break;
953966
case NL80211_IFTYPE_P2P_DEVICE:
954967
/* relies on synchronize_rcu() below */
955968
RCU_INIT_POINTER(local->p2p_sdata, NULL);
956969
/* fall through */
957-
case NL80211_IFTYPE_NAN:
958970
default:
959971
cancel_work_sync(&sdata->work);
960972
/*
@@ -1462,9 +1474,13 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
14621474
case NL80211_IFTYPE_WDS:
14631475
sdata->vif.bss_conf.bssid = NULL;
14641476
break;
1477+
case NL80211_IFTYPE_NAN:
1478+
idr_init(&sdata->u.nan.function_inst_ids);
1479+
spin_lock_init(&sdata->u.nan.func_lock);
1480+
sdata->vif.bss_conf.bssid = sdata->vif.addr;
1481+
break;
14651482
case NL80211_IFTYPE_AP_VLAN:
14661483
case NL80211_IFTYPE_P2P_DEVICE:
1467-
case NL80211_IFTYPE_NAN:
14681484
sdata->vif.bss_conf.bssid = sdata->vif.addr;
14691485
break;
14701486
case NL80211_IFTYPE_UNSPECIFIED:

net/mac80211/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
10631063

10641064
local->dynamic_ps_forced_timeout = -1;
10651065

1066+
if (!local->hw.max_nan_de_entries)
1067+
local->hw.max_nan_de_entries = IEEE80211_MAX_NAN_INSTANCE_ID;
1068+
10661069
result = ieee80211_wep_init(local);
10671070
if (result < 0)
10681071
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",

net/mac80211/trace.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,58 @@ TRACE_EVENT(drv_nan_change_conf,
17811781
)
17821782
);
17831783

1784+
TRACE_EVENT(drv_add_nan_func,
1785+
TP_PROTO(struct ieee80211_local *local,
1786+
struct ieee80211_sub_if_data *sdata,
1787+
const struct cfg80211_nan_func *func),
1788+
1789+
TP_ARGS(local, sdata, func),
1790+
TP_STRUCT__entry(
1791+
LOCAL_ENTRY
1792+
VIF_ENTRY
1793+
__field(u8, type)
1794+
__field(u8, inst_id)
1795+
),
1796+
1797+
TP_fast_assign(
1798+
LOCAL_ASSIGN;
1799+
VIF_ASSIGN;
1800+
__entry->type = func->type;
1801+
__entry->inst_id = func->instance_id;
1802+
),
1803+
1804+
TP_printk(
1805+
LOCAL_PR_FMT VIF_PR_FMT
1806+
", type: %u, inst_id: %u",
1807+
LOCAL_PR_ARG, VIF_PR_ARG, __entry->type, __entry->inst_id
1808+
)
1809+
);
1810+
1811+
TRACE_EVENT(drv_del_nan_func,
1812+
TP_PROTO(struct ieee80211_local *local,
1813+
struct ieee80211_sub_if_data *sdata,
1814+
u8 instance_id),
1815+
1816+
TP_ARGS(local, sdata, instance_id),
1817+
TP_STRUCT__entry(
1818+
LOCAL_ENTRY
1819+
VIF_ENTRY
1820+
__field(u8, instance_id)
1821+
),
1822+
1823+
TP_fast_assign(
1824+
LOCAL_ASSIGN;
1825+
VIF_ASSIGN;
1826+
__entry->instance_id = instance_id;
1827+
),
1828+
1829+
TP_printk(
1830+
LOCAL_PR_FMT VIF_PR_FMT
1831+
", instance_id: %u",
1832+
LOCAL_PR_ARG, VIF_PR_ARG, __entry->instance_id
1833+
)
1834+
);
1835+
17841836
/*
17851837
* Tracing for API calls that drivers call.
17861838
*/

0 commit comments

Comments
 (0)