Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / net / mac80211 / iface.c
index f75e5f1..9df26ad 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright 2005-2006, Devicescape Software, Inc.
  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014  Intel Mobile Communications GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -257,6 +258,15 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
        /* we hold the RTNL here so can safely walk the list */
        list_for_each_entry(nsdata, &local->interfaces, list) {
                if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
+                       /*
+                        * Only OCB and monitor mode may coexist
+                        */
+                       if ((sdata->vif.type == NL80211_IFTYPE_OCB &&
+                            nsdata->vif.type != NL80211_IFTYPE_MONITOR) ||
+                           (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+                            nsdata->vif.type == NL80211_IFTYPE_OCB))
+                               return -EBUSY;
+
                        /*
                         * Allow only a single IBSS interface to be up at any
                         * time. This is restricted because beacon distribution
@@ -520,6 +530,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
        case NL80211_IFTYPE_MONITOR:
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_P2P_DEVICE:
+       case NL80211_IFTYPE_OCB:
                /* no special treatment */
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
@@ -630,6 +641,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                case NL80211_IFTYPE_ADHOC:
                case NL80211_IFTYPE_AP:
                case NL80211_IFTYPE_MESH_POINT:
+               case NL80211_IFTYPE_OCB:
                        netif_carrier_off(dev);
                        break;
                case NL80211_IFTYPE_WDS:
@@ -765,10 +777,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        int i, flushed;
        struct ps_data *ps;
        struct cfg80211_chan_def chandef;
+       bool cancel_scan;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
-       if (rcu_access_pointer(local->scan_sdata) == sdata)
+       cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
+       if (cancel_scan)
                ieee80211_scan_cancel(local);
 
        /*
@@ -841,6 +855,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        sdata_lock(sdata);
        mutex_lock(&local->mtx);
        sdata->vif.csa_active = false;
+       if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               sdata->u.mgd.csa_waiting_bcn = false;
        if (sdata->csa_block_tx) {
                ieee80211_wake_vif_queues(local, sdata,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -897,6 +913,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                list_del(&sdata->u.vlan.list);
                mutex_unlock(&local->mtx);
                RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
+               /* see comment in the default case below */
+               ieee80211_free_keys(sdata, true);
                /* no need to tell driver */
                break;
        case NL80211_IFTYPE_MONITOR:
@@ -922,17 +940,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                /*
                 * When we get here, the interface is marked down.
                 * Free the remaining keys, if there are any
-                * (shouldn't be, except maybe in WDS mode?)
+                * (which can happen in AP mode if userspace sets
+                * keys before the interface is operating, and maybe
+                * also in WDS mode)
                 *
                 * Force the key freeing to always synchronize_net()
                 * to wait for the RX path in case it is using this
-                * interface enqueuing frames at this very time on
+                * interface enqueuing frames at this very time on
                 * another CPU.
                 */
                ieee80211_free_keys(sdata, true);
-
-               /* fall through */
-       case NL80211_IFTYPE_AP:
                skb_queue_purge(&sdata->skb_queue);
        }
 
@@ -990,6 +1007,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_recalc_ps(local, -1);
 
+       if (cancel_scan)
+               flush_delayed_work(&local->scan_work);
+
        if (local->open_count == 0) {
                ieee80211_stop_device(local);
 
@@ -1172,19 +1192,11 @@ static void ieee80211_iface_work(struct work_struct *work)
                        rx_agg = (void *)&skb->cb;
                        mutex_lock(&local->sta_mtx);
                        sta = sta_info_get_bss(sdata, rx_agg->addr);
-                       if (sta) {
-                               u16 last_seq;
-
-                               last_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(
-                                       sta->last_seq_ctrl[rx_agg->tid]));
-
+                       if (sta)
                                __ieee80211_start_rx_ba_session(sta,
-                                               0, 0,
-                                               ieee80211_sn_inc(last_seq),
-                                               1, rx_agg->tid,
+                                               0, 0, 0, 1, rx_agg->tid,
                                                IEEE80211_MAX_AMPDU_BUF,
-                                               false);
-                       }
+                                               false, true);
                        mutex_unlock(&local->sta_mtx);
                } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
                        rx_agg = (void *)&skb->cb;
@@ -1286,6 +1298,9 @@ static void ieee80211_iface_work(struct work_struct *work)
                        break;
                ieee80211_mesh_work(sdata);
                break;
+       case NL80211_IFTYPE_OCB:
+               ieee80211_ocb_work(sdata);
+               break;
        default:
                break;
        }
@@ -1305,6 +1320,9 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
 static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                                  enum nl80211_iftype type)
 {
+       static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff,
+                                                   0xff, 0xff, 0xff};
+
        /* clear type-dependent union */
        memset(&sdata->u, 0, sizeof(sdata->u));
 
@@ -1356,6 +1374,10 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
                ieee80211_sta_setup_sdata(sdata);
                break;
+       case NL80211_IFTYPE_OCB:
+               sdata->vif.bss_conf.bssid = bssid_wildcard;
+               ieee80211_ocb_setup_sdata(sdata);
+               break;
        case NL80211_IFTYPE_ADHOC:
                sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
                ieee80211_ibss_setup_sdata(sdata);
@@ -1403,6 +1425,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_OCB:
                /*
                 * Could maybe also all others here?
                 * Just not sure how that interacts
@@ -1418,6 +1441,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_OCB:
                /*
                 * Could probably support everything
                 * but WDS here (WDS do_open can fail
@@ -1676,7 +1700,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                }
 
                ieee80211_assign_perm_addr(local, ndev->perm_addr, type);
-               memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+               if (params && is_valid_ether_addr(params->macaddr))
+                       memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN);
+               else
+                       memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
                SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
 
                /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */