Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / net / mac80211 / iface.c
index b123a9e..638ec07 100644 (file)
@@ -43,6 +43,8 @@
  * by either the RTNL, the iflist_mtx or RCU.
  */
 
+static void ieee80211_iface_work(struct work_struct *work);
+
 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_chanctx_conf *chanctx_conf;
@@ -188,7 +190,7 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
                        continue;
 
                if (iter->vif.type == NL80211_IFTYPE_MONITOR &&
-                   !(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+                   !(iter->u.mntr.flags & MONITOR_FLAG_ACTIVE))
                        continue;
 
                m = iter->vif.addr;
@@ -217,7 +219,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
                return -EBUSY;
 
        if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
-           !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+           !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
                check_dup = false;
 
        ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup);
@@ -325,6 +327,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
        int n_queues = sdata->local->hw.queues;
        int i;
 
+       if (iftype == NL80211_IFTYPE_NAN)
+               return 0;
+
        if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                        if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
@@ -357,7 +362,7 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
                                    const int offset)
 {
        struct ieee80211_local *local = sdata->local;
-       u32 flags = sdata->u.mntr_flags;
+       u32 flags = sdata->u.mntr.flags;
 
 #define ADJUST(_f, _s) do {                                    \
        if (flags & MONITOR_FLAG_##_f)                          \
@@ -448,6 +453,9 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                return ret;
        }
 
+       skb_queue_head_init(&sdata->skb_queue);
+       INIT_WORK(&sdata->work, ieee80211_iface_work);
+
        return 0;
 }
 
@@ -540,6 +548,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_P2P_DEVICE:
        case NL80211_IFTYPE_OCB:
+       case NL80211_IFTYPE_NAN:
                /* no special treatment */
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
@@ -589,12 +598,12 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                }
                break;
        case NL80211_IFTYPE_MONITOR:
-               if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
+               if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
                        local->cooked_mntrs++;
                        break;
                }
 
-               if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
+               if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
                        res = drv_add_interface(local, sdata);
                        if (res)
                                goto err_stop;
@@ -641,7 +650,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                        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);
                ieee80211_bss_info_change_notify(sdata, changed);
 
@@ -655,6 +665,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                        break;
                case NL80211_IFTYPE_WDS:
                case NL80211_IFTYPE_P2P_DEVICE:
+               case NL80211_IFTYPE_NAN:
                        break;
                default:
                        /* not reached */
@@ -787,6 +798,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        struct ps_data *ps;
        struct cfg80211_chan_def chandef;
        bool cancel_scan;
+       struct cfg80211_nan_func *func;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
@@ -926,7 +938,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                /* no need to tell driver */
                break;
        case NL80211_IFTYPE_MONITOR:
-               if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
+               if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) {
                        local->cooked_mntrs--;
                        break;
                }
@@ -939,6 +951,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
                ieee80211_adjust_monitor_flags(sdata, -1);
                break;
+       case NL80211_IFTYPE_NAN:
+               /* clean all the functions */
+               spin_lock_bh(&sdata->u.nan.func_lock);
+
+               idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
+                       idr_remove(&sdata->u.nan.function_inst_ids, i);
+                       cfg80211_free_nan_func(func);
+               }
+               idr_destroy(&sdata->u.nan.function_inst_ids);
+
+               spin_unlock_bh(&sdata->u.nan.func_lock);
+               break;
        case NL80211_IFTYPE_P2P_DEVICE:
                /* relies on synchronize_rcu() below */
                RCU_INIT_POINTER(local->p2p_sdata, NULL);
@@ -1012,7 +1036,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                ieee80211_recalc_idle(local);
                mutex_unlock(&local->mtx);
 
-               if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+               if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
                        break;
 
                /* fall through */
@@ -1444,12 +1468,17 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
        case NL80211_IFTYPE_MONITOR:
                sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
                sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
-               sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
+               sdata->u.mntr.flags = MONITOR_FLAG_CONTROL |
                                      MONITOR_FLAG_OTHER_BSS;
                break;
        case NL80211_IFTYPE_WDS:
                sdata->vif.bss_conf.bssid = NULL;
                break;
+       case NL80211_IFTYPE_NAN:
+               idr_init(&sdata->u.nan.function_inst_ids);
+               spin_lock_init(&sdata->u.nan.func_lock);
+               sdata->vif.bss_conf.bssid = sdata->vif.addr;
+               break;
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_P2P_DEVICE:
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
@@ -1717,7 +1746,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        ASSERT_RTNL();
 
-       if (type == NL80211_IFTYPE_P2P_DEVICE) {
+       if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) {
                struct wireless_dev *wdev;
 
                sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size,