Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / iface.c
index bab5c63c0bad798529b3c5a964db995be4eef6b0..ed1edac143729cc117c1cb63c5519285acff13a7 100644 (file)
@@ -338,7 +338,7 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
        if ((iftype != NL80211_IFTYPE_AP &&
             iftype != NL80211_IFTYPE_P2P_GO &&
             iftype != NL80211_IFTYPE_MESH_POINT) ||
-           !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) {
+           !ieee80211_hw_check(&sdata->local->hw, QUEUE_CONTROL)) {
                sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
                return 0;
        }
@@ -378,7 +378,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
        int i;
 
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-               if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
+               if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
                        sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
                else if (local->hw.queues >= IEEE80211_NUM_ACS)
                        sdata->vif.hw_queue[i] = i;
@@ -393,7 +393,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        struct ieee80211_sub_if_data *sdata;
        int ret;
 
-       if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
+       if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
                return 0;
 
        ASSERT_RTNL();
@@ -454,7 +454,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
 
-       if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
+       if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
                return;
 
        ASSERT_RTNL();
@@ -522,6 +522,12 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
                       sizeof(sdata->vif.hw_queue));
                sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef;
+
+               mutex_lock(&local->key_mtx);
+               sdata->crypto_tx_tailroom_needed_cnt +=
+                       master->crypto_tx_tailroom_needed_cnt;
+               mutex_unlock(&local->key_mtx);
+
                break;
                }
        case NL80211_IFTYPE_AP:
@@ -697,9 +703,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
        if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
                atomic_inc(&local->iff_allmultis);
 
-       if (sdata->flags & IEEE80211_SDATA_PROMISC)
-               atomic_inc(&local->iff_promiscs);
-
        if (coming_up)
                local->open_count++;
 
@@ -829,13 +832,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                     ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
                      (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)));
 
-       /* don't count this interface for promisc/allmulti while it is down */
+       /* don't count this interface for allmulti while it is down */
        if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
                atomic_dec(&local->iff_allmultis);
 
-       if (sdata->flags & IEEE80211_SDATA_PROMISC)
-               atomic_dec(&local->iff_promiscs);
-
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
                local->fif_pspoll--;
                local->fif_probe_req--;
@@ -1049,12 +1049,10 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       int allmulti, promisc, sdata_allmulti, sdata_promisc;
+       int allmulti, sdata_allmulti;
 
        allmulti = !!(dev->flags & IFF_ALLMULTI);
-       promisc = !!(dev->flags & IFF_PROMISC);
        sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
-       sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
 
        if (allmulti != sdata_allmulti) {
                if (dev->flags & IFF_ALLMULTI)
@@ -1064,13 +1062,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
                sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
        }
 
-       if (promisc != sdata_promisc) {
-               if (dev->flags & IFF_PROMISC)
-                       atomic_inc(&local->iff_promiscs);
-               else
-                       atomic_dec(&local->iff_promiscs);
-               sdata->flags ^= IEEE80211_SDATA_PROMISC;
-       }
        spin_lock_bh(&local->filter_lock);
        __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
        spin_unlock_bh(&local->filter_lock);
@@ -1111,6 +1102,35 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev,
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
 
+static struct rtnl_link_stats64 *
+ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+       int i;
+
+       for_each_possible_cpu(i) {
+               const struct pcpu_sw_netstats *tstats;
+               u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+               unsigned int start;
+
+               tstats = per_cpu_ptr(dev->tstats, i);
+
+               do {
+                       start = u64_stats_fetch_begin_irq(&tstats->syncp);
+                       rx_packets = tstats->rx_packets;
+                       tx_packets = tstats->tx_packets;
+                       rx_bytes = tstats->rx_bytes;
+                       tx_bytes = tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
+
+               stats->rx_packets += rx_packets;
+               stats->tx_packets += tx_packets;
+               stats->rx_bytes   += rx_bytes;
+               stats->tx_bytes   += tx_bytes;
+       }
+
+       return stats;
+}
+
 static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_open               = ieee80211_open,
        .ndo_stop               = ieee80211_stop,
@@ -1120,6 +1140,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_netdev_select_queue,
+       .ndo_get_stats64        = ieee80211_get_stats64,
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
@@ -1153,14 +1174,21 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
        .ndo_change_mtu         = ieee80211_change_mtu,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_monitor_select_queue,
+       .ndo_get_stats64        = ieee80211_get_stats64,
 };
 
+static void ieee80211_if_free(struct net_device *dev)
+{
+       free_percpu(dev->tstats);
+       free_netdev(dev);
+}
+
 static void ieee80211_if_setup(struct net_device *dev)
 {
        ether_setup(dev);
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->netdev_ops = &ieee80211_dataif_ops;
-       dev->destructor = free_netdev;
+       dev->destructor = ieee80211_if_free;
 }
 
 static void ieee80211_iface_work(struct work_struct *work)
@@ -1558,7 +1586,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_P2P_GO:
-               if (local->hw.flags & IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF) {
+               if (ieee80211_hw_check(&local->hw, P2P_DEV_ADDR_FOR_INTF)) {
                        list_for_each_entry(sdata, &local->interfaces, list) {
                                if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
                                        continue;
@@ -1701,6 +1729,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                        return -ENOMEM;
                dev_net_set(ndev, wiphy_net(local->hw.wiphy));
 
+               ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+               if (!ndev->tstats) {
+                       free_netdev(ndev);
+                       return -ENOMEM;
+               }
+
                ndev->needed_headroom = local->tx_headroom +
                                        4*6 /* four MAC addresses */
                                        + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */