proc: add LSM hook checks to /proc/<tid>/timerslack_ns
[cascardo/linux.git] / net / mac80211 / cfg.c
index 38fdb53..fd6541f 100644 (file)
@@ -174,6 +174,8 @@ static int ieee80211_start_nan(struct wiphy *wiphy,
        if (ret)
                ieee80211_sdata_stop(sdata);
 
+       sdata->u.nan.conf = *conf;
+
        return ret;
 }
 
@@ -216,6 +218,84 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy,
        return ret;
 }
 
+static int ieee80211_add_nan_func(struct wiphy *wiphy,
+                                 struct wireless_dev *wdev,
+                                 struct cfg80211_nan_func *nan_func)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+       int ret;
+
+       if (sdata->vif.type != NL80211_IFTYPE_NAN)
+               return -EOPNOTSUPP;
+
+       if (!ieee80211_sdata_running(sdata))
+               return -ENETDOWN;
+
+       spin_lock_bh(&sdata->u.nan.func_lock);
+
+       ret = idr_alloc(&sdata->u.nan.function_inst_ids,
+                       nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
+                       GFP_ATOMIC);
+       spin_unlock_bh(&sdata->u.nan.func_lock);
+
+       if (ret < 0)
+               return ret;
+
+       nan_func->instance_id = ret;
+
+       WARN_ON(nan_func->instance_id == 0);
+
+       ret = drv_add_nan_func(sdata->local, sdata, nan_func);
+       if (ret) {
+               spin_lock_bh(&sdata->u.nan.func_lock);
+               idr_remove(&sdata->u.nan.function_inst_ids,
+                          nan_func->instance_id);
+               spin_unlock_bh(&sdata->u.nan.func_lock);
+       }
+
+       return ret;
+}
+
+static struct cfg80211_nan_func *
+ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
+                                 u64 cookie)
+{
+       struct cfg80211_nan_func *func;
+       int id;
+
+       lockdep_assert_held(&sdata->u.nan.func_lock);
+
+       idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
+               if (func->cookie == cookie)
+                       return func;
+       }
+
+       return NULL;
+}
+
+static void ieee80211_del_nan_func(struct wiphy *wiphy,
+                                 struct wireless_dev *wdev, u64 cookie)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+       struct cfg80211_nan_func *func;
+       u8 instance_id = 0;
+
+       if (sdata->vif.type != NL80211_IFTYPE_NAN ||
+           !ieee80211_sdata_running(sdata))
+               return;
+
+       spin_lock_bh(&sdata->u.nan.func_lock);
+
+       func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
+       if (func)
+               instance_id = func->instance_id;
+
+       spin_unlock_bh(&sdata->u.nan.func_lock);
+
+       if (instance_id)
+               drv_del_nan_func(sdata->local, sdata, instance_id);
+}
+
 static int ieee80211_set_noack_map(struct wiphy *wiphy,
                                  struct net_device *dev,
                                  u16 noack_map)
@@ -3443,6 +3523,63 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
        return -ENOENT;
 }
 
+void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
+                                  u8 inst_id,
+                                  enum nl80211_nan_func_term_reason reason,
+                                  gfp_t gfp)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct cfg80211_nan_func *func;
+       u64 cookie;
+
+       if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
+               return;
+
+       spin_lock_bh(&sdata->u.nan.func_lock);
+
+       func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
+       if (WARN_ON(!func)) {
+               spin_unlock_bh(&sdata->u.nan.func_lock);
+               return;
+       }
+
+       cookie = func->cookie;
+       idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
+
+       spin_unlock_bh(&sdata->u.nan.func_lock);
+
+       cfg80211_free_nan_func(func);
+
+       cfg80211_nan_func_terminated(ieee80211_vif_to_wdev(vif), inst_id,
+                                    reason, cookie, gfp);
+}
+EXPORT_SYMBOL(ieee80211_nan_func_terminated);
+
+void ieee80211_nan_func_match(struct ieee80211_vif *vif,
+                             struct cfg80211_nan_match_params *match,
+                             gfp_t gfp)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct cfg80211_nan_func *func;
+
+       if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
+               return;
+
+       spin_lock_bh(&sdata->u.nan.func_lock);
+
+       func = idr_find(&sdata->u.nan.function_inst_ids,  match->inst_id);
+       if (WARN_ON(!func)) {
+               spin_unlock_bh(&sdata->u.nan.func_lock);
+               return;
+       }
+       match->cookie = func->cookie;
+
+       spin_unlock_bh(&sdata->u.nan.func_lock);
+
+       cfg80211_nan_match(ieee80211_vif_to_wdev(vif), match, gfp);
+}
+EXPORT_SYMBOL(ieee80211_nan_func_match);
+
 const struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -3531,4 +3668,6 @@ const struct cfg80211_ops mac80211_config_ops = {
        .start_nan = ieee80211_start_nan,
        .stop_nan = ieee80211_stop_nan,
        .nan_change_conf = ieee80211_nan_change_conf,
+       .add_nan_func = ieee80211_add_nan_func,
+       .del_nan_func = ieee80211_del_nan_func,
 };