diff options
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch')
-rw-r--r-- | package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch | 1124 |
1 files changed, 0 insertions, 1124 deletions
diff --git a/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch b/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch deleted file mode 100644 index 0bfb10cdb0..0000000000 --- a/package/kernel/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch +++ /dev/null @@ -1,1124 +0,0 @@ -From: Felix Fietkau <nbd@nbd.name> -Date: Tue, 8 Sep 2020 12:16:26 +0200 -Subject: [PATCH] mac80211: reorganize code to remove a forward - declaration - -Remove the newly added ieee80211_set_vif_encap_ops declaration. -No further code changes - -Signed-off-by: Felix Fietkau <nbd@nbd.name> ---- - ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -43,7 +43,6 @@ - */ - - static void ieee80211_iface_work(struct work_struct *work); --static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata); - - bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) - { -@@ -349,6 +348,518 @@ static int ieee80211_check_queues(struct - return 0; - } - -+static int ieee80211_open(struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ int err; -+ -+ /* fail early if user set an invalid address */ -+ if (!is_valid_ether_addr(dev->dev_addr)) -+ return -EADDRNOTAVAIL; -+ -+ err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); -+ if (err) -+ return err; -+ -+ return ieee80211_do_open(&sdata->wdev, true); -+} -+ -+static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, -+ bool going_down) -+{ -+ struct ieee80211_local *local = sdata->local; -+ unsigned long flags; -+ struct sk_buff *skb, *tmp; -+ u32 hw_reconf_flags = 0; -+ int i, flushed; -+ struct ps_data *ps; -+ struct cfg80211_chan_def chandef; -+ bool cancel_scan; -+ struct cfg80211_nan_func *func; -+ -+ clear_bit(SDATA_STATE_RUNNING, &sdata->state); -+ -+ cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; -+ if (cancel_scan) -+ ieee80211_scan_cancel(local); -+ -+ /* -+ * Stop TX on this interface first. -+ */ -+ if (sdata->dev) -+ netif_tx_stop_all_queues(sdata->dev); -+ -+ ieee80211_roc_purge(local, sdata); -+ -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_STATION: -+ ieee80211_mgd_stop(sdata); -+ break; -+ case NL80211_IFTYPE_ADHOC: -+ ieee80211_ibss_stop(sdata); -+ break; -+ case NL80211_IFTYPE_MONITOR: -+ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) -+ break; -+ list_del_rcu(&sdata->u.mntr.list); -+ break; -+ default: -+ break; -+ } -+ -+ /* -+ * Remove all stations associated with this interface. -+ * -+ * This must be done before calling ops->remove_interface() -+ * because otherwise we can later invoke ops->sta_notify() -+ * whenever the STAs are removed, and that invalidates driver -+ * assumptions about always getting a vif pointer that is valid -+ * (because if we remove a STA after ops->remove_interface() -+ * the driver will have removed the vif info already!) -+ * -+ * In WDS mode a station must exist here and be flushed, for -+ * AP_VLANs stations may exist since there's nothing else that -+ * would have removed them, but in other modes there shouldn't -+ * be any stations. -+ */ -+ flushed = sta_info_flush(sdata); -+ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && -+ ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || -+ (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); -+ -+ /* don't count this interface for allmulti while it is down */ -+ if (sdata->flags & IEEE80211_SDATA_ALLMULTI) -+ atomic_dec(&local->iff_allmultis); -+ -+ if (sdata->vif.type == NL80211_IFTYPE_AP) { -+ local->fif_pspoll--; -+ local->fif_probe_req--; -+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { -+ local->fif_probe_req--; -+ } -+ -+ if (sdata->dev) { -+ netif_addr_lock_bh(sdata->dev); -+ spin_lock_bh(&local->filter_lock); -+ __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, -+ sdata->dev->addr_len); -+ spin_unlock_bh(&local->filter_lock); -+ netif_addr_unlock_bh(sdata->dev); -+ } -+ -+ del_timer_sync(&local->dynamic_ps_timer); -+ cancel_work_sync(&local->dynamic_ps_enable_work); -+ -+ cancel_work_sync(&sdata->recalc_smps); -+ 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); -+ sdata->csa_block_tx = false; -+ } -+ mutex_unlock(&local->mtx); -+ sdata_unlock(sdata); -+ -+ cancel_work_sync(&sdata->csa_finalize_work); -+ -+ cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); -+ -+ if (sdata->wdev.cac_started) { -+ chandef = sdata->vif.bss_conf.chandef; -+ WARN_ON(local->suspended); -+ mutex_lock(&local->mtx); -+ ieee80211_vif_release_channel(sdata); -+ mutex_unlock(&local->mtx); -+ cfg80211_cac_event(sdata->dev, &chandef, -+ NL80211_RADAR_CAC_ABORTED, -+ GFP_KERNEL); -+ } -+ -+ /* APs need special treatment */ -+ if (sdata->vif.type == NL80211_IFTYPE_AP) { -+ struct ieee80211_sub_if_data *vlan, *tmpsdata; -+ -+ /* down all dependent devices, that is VLANs */ -+ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, -+ u.vlan.list) -+ dev_close(vlan->dev); -+ WARN_ON(!list_empty(&sdata->u.ap.vlans)); -+ } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { -+ /* remove all packets in parent bc_buf pointing to this dev */ -+ ps = &sdata->bss->ps; -+ -+ spin_lock_irqsave(&ps->bc_buf.lock, flags); -+ skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { -+ if (skb->dev == sdata->dev) { -+ __skb_unlink(skb, &ps->bc_buf); -+ local->total_ps_buffered--; -+ ieee80211_free_txskb(&local->hw, skb); -+ } -+ } -+ spin_unlock_irqrestore(&ps->bc_buf.lock, flags); -+ } -+ -+ if (going_down) -+ local->open_count--; -+ -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_AP_VLAN: -+ mutex_lock(&local->mtx); -+ 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: -+ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { -+ local->cooked_mntrs--; -+ break; -+ } -+ -+ local->monitors--; -+ if (local->monitors == 0) { -+ local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; -+ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; -+ } -+ -+ 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); -+ fallthrough; -+ default: -+ cancel_work_sync(&sdata->work); -+ /* -+ * When we get here, the interface is marked down. -+ * Free the remaining keys, if there are any -+ * (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 -+ * another CPU. -+ */ -+ ieee80211_free_keys(sdata, true); -+ skb_queue_purge(&sdata->skb_queue); -+ } -+ -+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); -+ for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { -+ skb_queue_walk_safe(&local->pending[i], skb, tmp) { -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ if (info->control.vif == &sdata->vif) { -+ __skb_unlink(skb, &local->pending[i]); -+ ieee80211_free_txskb(&local->hw, skb); -+ } -+ } -+ } -+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -+ -+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ ieee80211_txq_remove_vlan(local, sdata); -+ -+ sdata->bss = NULL; -+ -+ if (local->open_count == 0) -+ ieee80211_clear_tx_pending(local); -+ -+ sdata->vif.bss_conf.beacon_int = 0; -+ -+ /* -+ * If the interface goes down while suspended, presumably because -+ * the device was unplugged and that happens before our resume, -+ * then the driver is already unconfigured and the remainder of -+ * this function isn't needed. -+ * XXX: what about WoWLAN? If the device has software state, e.g. -+ * memory allocated, it might expect teardown commands from -+ * mac80211 here? -+ */ -+ if (local->suspended) { -+ WARN_ON(local->wowlan); -+ WARN_ON(rtnl_dereference(local->monitor_sdata)); -+ return; -+ } -+ -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_AP_VLAN: -+ break; -+ case NL80211_IFTYPE_MONITOR: -+ if (local->monitors == 0) -+ ieee80211_del_virtual_monitor(local); -+ -+ mutex_lock(&local->mtx); -+ ieee80211_recalc_idle(local); -+ mutex_unlock(&local->mtx); -+ -+ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) -+ break; -+ -+ fallthrough; -+ default: -+ if (going_down) -+ drv_remove_interface(local, sdata); -+ } -+ -+ ieee80211_recalc_ps(local); -+ -+ if (cancel_scan) -+ flush_delayed_work(&local->scan_work); -+ -+ if (local->open_count == 0) { -+ ieee80211_stop_device(local); -+ -+ /* no reconfiguring after stop! */ -+ return; -+ } -+ -+ /* do after stop to avoid reconfiguring when we stop anyway */ -+ ieee80211_configure_filter(local); -+ ieee80211_hw_config(local, hw_reconf_flags); -+ -+ if (local->monitors == local->open_count) -+ ieee80211_add_virtual_monitor(local); -+} -+ -+static int ieee80211_stop(struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ ieee80211_do_stop(sdata, true); -+ -+ return 0; -+} -+ -+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, sdata_allmulti; -+ -+ allmulti = !!(dev->flags & IFF_ALLMULTI); -+ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); -+ -+ if (allmulti != sdata_allmulti) { -+ if (dev->flags & IFF_ALLMULTI) -+ atomic_inc(&local->iff_allmultis); -+ else -+ atomic_dec(&local->iff_allmultis); -+ sdata->flags ^= IEEE80211_SDATA_ALLMULTI; -+ } -+ -+ spin_lock_bh(&local->filter_lock); -+ __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); -+ spin_unlock_bh(&local->filter_lock); -+ ieee80211_queue_work(&local->hw, &local->reconfig_filter); -+} -+ -+/* -+ * Called when the netdev is removed or, by the code below, before -+ * the interface type changes. -+ */ -+static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) -+{ -+ int i; -+ -+ /* free extra data */ -+ ieee80211_free_keys(sdata, false); -+ -+ ieee80211_debugfs_remove_netdev(sdata); -+ -+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) -+ __skb_queue_purge(&sdata->fragments[i].skb_list); -+ sdata->fragment_next = 0; -+ -+ if (ieee80211_vif_is_mesh(&sdata->vif)) -+ ieee80211_mesh_teardown_sdata(sdata); -+} -+ -+static void ieee80211_uninit(struct net_device *dev) -+{ -+ ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); -+} -+ -+#if LINUX_VERSION_IS_GEQ(5,2,0) -+static u16 ieee80211_netdev_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ struct net_device *sb_dev) -+#elif LINUX_VERSION_IS_GEQ(4,19,0) -+static u16 ieee80211_netdev_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ struct net_device *sb_dev, -+ select_queue_fallback_t fallback) -+#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ -+ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) -+static u16 ieee80211_netdev_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ void *accel_priv, -+ select_queue_fallback_t fallback) -+#elif LINUX_VERSION_IS_GEQ(3,13,0) -+static u16 ieee80211_netdev_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ void *accel_priv) -+#else -+static u16 ieee80211_netdev_select_queue(struct net_device *dev, -+ struct sk_buff *skb) -+#endif -+{ -+ return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); -+} -+ -+static void -+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(netdev_tstats(dev), 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; -+ } -+} -+#if LINUX_VERSION_IS_LESS(4,11,0) -+/* Just declare it here to keep sparse happy */ -+struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, -+ struct rtnl_link_stats64 *stats); -+struct rtnl_link_stats64 * -+bp_ieee80211_get_stats64(struct net_device *dev, -+ struct rtnl_link_stats64 *stats){ -+ ieee80211_get_stats64(dev, stats); -+ return stats; -+} -+#endif -+ -+static const struct net_device_ops ieee80211_dataif_ops = { -+ .ndo_open = ieee80211_open, -+ .ndo_stop = ieee80211_stop, -+ .ndo_uninit = ieee80211_uninit, -+ .ndo_start_xmit = ieee80211_subif_start_xmit, -+ .ndo_set_rx_mode = ieee80211_set_multicast_list, -+ .ndo_set_mac_address = ieee80211_change_mac, -+ .ndo_select_queue = ieee80211_netdev_select_queue, -+#if LINUX_VERSION_IS_GEQ(4,11,0) -+ .ndo_get_stats64 = ieee80211_get_stats64, -+#else -+ .ndo_get_stats64 = bp_ieee80211_get_stats64, -+#endif -+ -+}; -+ -+#if LINUX_VERSION_IS_GEQ(5,2,0) -+static u16 ieee80211_monitor_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ struct net_device *sb_dev) -+#elif LINUX_VERSION_IS_GEQ(4,19,0) -+static u16 ieee80211_monitor_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ struct net_device *sb_dev, -+ select_queue_fallback_t fallback) -+#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ -+ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) -+static u16 ieee80211_monitor_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ void *accel_priv, -+ select_queue_fallback_t fallback) -+#elif LINUX_VERSION_IS_GEQ(3,13,0) -+static u16 ieee80211_monitor_select_queue(struct net_device *dev, -+ struct sk_buff *skb, -+ void *accel_priv) -+#else -+static u16 ieee80211_monitor_select_queue(struct net_device *dev, -+ struct sk_buff *skb) -+#endif -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_local *local = sdata->local; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct ieee80211_hdr *hdr; -+ int len_rthdr; -+ -+ if (local->hw.queues < IEEE80211_NUM_ACS) -+ return 0; -+ -+ /* reset flags and info before parsing radiotap header */ -+ memset(info, 0, sizeof(*info)); -+ -+ if (!ieee80211_parse_tx_radiotap(skb, dev)) -+ return 0; /* doesn't matter, frame will be dropped */ -+ -+ len_rthdr = ieee80211_get_radiotap_len(skb->data); -+ hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); -+ if (skb->len < len_rthdr + 2 || -+ skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control)) -+ return 0; /* doesn't matter, frame will be dropped */ -+ -+ return ieee80211_select_queue_80211(sdata, skb, hdr); -+} -+ -+static const struct net_device_ops ieee80211_monitorif_ops = { -+ .ndo_open = ieee80211_open, -+ .ndo_stop = ieee80211_stop, -+ .ndo_uninit = ieee80211_uninit, -+ .ndo_start_xmit = ieee80211_monitor_start_xmit, -+ .ndo_set_rx_mode = ieee80211_set_multicast_list, -+ .ndo_set_mac_address = ieee80211_change_mac, -+ .ndo_select_queue = ieee80211_monitor_select_queue, -+#if LINUX_VERSION_IS_GEQ(4,11,0) -+ .ndo_get_stats64 = ieee80211_get_stats64, -+#else -+ .ndo_get_stats64 = bp_ieee80211_get_stats64, -+#endif -+ -+}; -+ -+static const struct net_device_ops ieee80211_dataif_8023_ops = { -+ .ndo_open = ieee80211_open, -+ .ndo_stop = ieee80211_stop, -+ .ndo_uninit = ieee80211_uninit, -+ .ndo_start_xmit = ieee80211_subif_start_xmit_8023, -+ .ndo_set_rx_mode = ieee80211_set_multicast_list, -+ .ndo_set_mac_address = ieee80211_change_mac, -+ .ndo_select_queue = ieee80211_netdev_select_queue, -+#if LINUX_VERSION_IS_GEQ(4,11,0) -+ .ndo_get_stats64 = ieee80211_get_stats64, -+#else -+ .ndo_get_stats64 = bp_ieee80211_get_stats64, -+#endif -+ -+}; -+ - static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) - { - switch (iftype) { -@@ -389,6 +900,31 @@ static bool ieee80211_set_sdata_offload_ - return true; - } - -+static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) -+{ -+ struct ieee80211_local *local = sdata->local; -+ struct ieee80211_sub_if_data *bss = sdata; -+ bool enabled; -+ -+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { -+ if (!sdata->bss) -+ return; -+ -+ bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); -+ } -+ -+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || -+ !ieee80211_iftype_supports_encap_offload(bss->vif.type)) -+ return; -+ -+ enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; -+ if (sdata->wdev.use_4addr && -+ !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) -+ enabled = false; -+ -+ sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : -+ &ieee80211_dataif_ops; -+} - - static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata) - { -@@ -866,518 +1402,6 @@ int ieee80211_do_open(struct wireless_de - return res; - } - --static int ieee80211_open(struct net_device *dev) --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- int err; -- -- /* fail early if user set an invalid address */ -- if (!is_valid_ether_addr(dev->dev_addr)) -- return -EADDRNOTAVAIL; -- -- err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); -- if (err) -- return err; -- -- return ieee80211_do_open(&sdata->wdev, true); --} -- --static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, -- bool going_down) --{ -- struct ieee80211_local *local = sdata->local; -- unsigned long flags; -- struct sk_buff *skb, *tmp; -- u32 hw_reconf_flags = 0; -- int i, flushed; -- struct ps_data *ps; -- struct cfg80211_chan_def chandef; -- bool cancel_scan; -- struct cfg80211_nan_func *func; -- -- clear_bit(SDATA_STATE_RUNNING, &sdata->state); -- -- cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; -- if (cancel_scan) -- ieee80211_scan_cancel(local); -- -- /* -- * Stop TX on this interface first. -- */ -- if (sdata->dev) -- netif_tx_stop_all_queues(sdata->dev); -- -- ieee80211_roc_purge(local, sdata); -- -- switch (sdata->vif.type) { -- case NL80211_IFTYPE_STATION: -- ieee80211_mgd_stop(sdata); -- break; -- case NL80211_IFTYPE_ADHOC: -- ieee80211_ibss_stop(sdata); -- break; -- case NL80211_IFTYPE_MONITOR: -- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) -- break; -- list_del_rcu(&sdata->u.mntr.list); -- break; -- default: -- break; -- } -- -- /* -- * Remove all stations associated with this interface. -- * -- * This must be done before calling ops->remove_interface() -- * because otherwise we can later invoke ops->sta_notify() -- * whenever the STAs are removed, and that invalidates driver -- * assumptions about always getting a vif pointer that is valid -- * (because if we remove a STA after ops->remove_interface() -- * the driver will have removed the vif info already!) -- * -- * In WDS mode a station must exist here and be flushed, for -- * AP_VLANs stations may exist since there's nothing else that -- * would have removed them, but in other modes there shouldn't -- * be any stations. -- */ -- flushed = sta_info_flush(sdata); -- WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && -- ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || -- (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); -- -- /* don't count this interface for allmulti while it is down */ -- if (sdata->flags & IEEE80211_SDATA_ALLMULTI) -- atomic_dec(&local->iff_allmultis); -- -- if (sdata->vif.type == NL80211_IFTYPE_AP) { -- local->fif_pspoll--; -- local->fif_probe_req--; -- } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { -- local->fif_probe_req--; -- } -- -- if (sdata->dev) { -- netif_addr_lock_bh(sdata->dev); -- spin_lock_bh(&local->filter_lock); -- __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, -- sdata->dev->addr_len); -- spin_unlock_bh(&local->filter_lock); -- netif_addr_unlock_bh(sdata->dev); -- } -- -- del_timer_sync(&local->dynamic_ps_timer); -- cancel_work_sync(&local->dynamic_ps_enable_work); -- -- cancel_work_sync(&sdata->recalc_smps); -- 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); -- sdata->csa_block_tx = false; -- } -- mutex_unlock(&local->mtx); -- sdata_unlock(sdata); -- -- cancel_work_sync(&sdata->csa_finalize_work); -- -- cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); -- -- if (sdata->wdev.cac_started) { -- chandef = sdata->vif.bss_conf.chandef; -- WARN_ON(local->suspended); -- mutex_lock(&local->mtx); -- ieee80211_vif_release_channel(sdata); -- mutex_unlock(&local->mtx); -- cfg80211_cac_event(sdata->dev, &chandef, -- NL80211_RADAR_CAC_ABORTED, -- GFP_KERNEL); -- } -- -- /* APs need special treatment */ -- if (sdata->vif.type == NL80211_IFTYPE_AP) { -- struct ieee80211_sub_if_data *vlan, *tmpsdata; -- -- /* down all dependent devices, that is VLANs */ -- list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, -- u.vlan.list) -- dev_close(vlan->dev); -- WARN_ON(!list_empty(&sdata->u.ap.vlans)); -- } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { -- /* remove all packets in parent bc_buf pointing to this dev */ -- ps = &sdata->bss->ps; -- -- spin_lock_irqsave(&ps->bc_buf.lock, flags); -- skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { -- if (skb->dev == sdata->dev) { -- __skb_unlink(skb, &ps->bc_buf); -- local->total_ps_buffered--; -- ieee80211_free_txskb(&local->hw, skb); -- } -- } -- spin_unlock_irqrestore(&ps->bc_buf.lock, flags); -- } -- -- if (going_down) -- local->open_count--; -- -- switch (sdata->vif.type) { -- case NL80211_IFTYPE_AP_VLAN: -- mutex_lock(&local->mtx); -- 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: -- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { -- local->cooked_mntrs--; -- break; -- } -- -- local->monitors--; -- if (local->monitors == 0) { -- local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; -- hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; -- } -- -- 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); -- fallthrough; -- default: -- cancel_work_sync(&sdata->work); -- /* -- * When we get here, the interface is marked down. -- * Free the remaining keys, if there are any -- * (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 -- * another CPU. -- */ -- ieee80211_free_keys(sdata, true); -- skb_queue_purge(&sdata->skb_queue); -- } -- -- spin_lock_irqsave(&local->queue_stop_reason_lock, flags); -- for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { -- skb_queue_walk_safe(&local->pending[i], skb, tmp) { -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- if (info->control.vif == &sdata->vif) { -- __skb_unlink(skb, &local->pending[i]); -- ieee80211_free_txskb(&local->hw, skb); -- } -- } -- } -- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); -- -- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -- ieee80211_txq_remove_vlan(local, sdata); -- -- sdata->bss = NULL; -- -- if (local->open_count == 0) -- ieee80211_clear_tx_pending(local); -- -- sdata->vif.bss_conf.beacon_int = 0; -- -- /* -- * If the interface goes down while suspended, presumably because -- * the device was unplugged and that happens before our resume, -- * then the driver is already unconfigured and the remainder of -- * this function isn't needed. -- * XXX: what about WoWLAN? If the device has software state, e.g. -- * memory allocated, it might expect teardown commands from -- * mac80211 here? -- */ -- if (local->suspended) { -- WARN_ON(local->wowlan); -- WARN_ON(rtnl_dereference(local->monitor_sdata)); -- return; -- } -- -- switch (sdata->vif.type) { -- case NL80211_IFTYPE_AP_VLAN: -- break; -- case NL80211_IFTYPE_MONITOR: -- if (local->monitors == 0) -- ieee80211_del_virtual_monitor(local); -- -- mutex_lock(&local->mtx); -- ieee80211_recalc_idle(local); -- mutex_unlock(&local->mtx); -- -- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) -- break; -- -- fallthrough; -- default: -- if (going_down) -- drv_remove_interface(local, sdata); -- } -- -- ieee80211_recalc_ps(local); -- -- if (cancel_scan) -- flush_delayed_work(&local->scan_work); -- -- if (local->open_count == 0) { -- ieee80211_stop_device(local); -- -- /* no reconfiguring after stop! */ -- return; -- } -- -- /* do after stop to avoid reconfiguring when we stop anyway */ -- ieee80211_configure_filter(local); -- ieee80211_hw_config(local, hw_reconf_flags); -- -- if (local->monitors == local->open_count) -- ieee80211_add_virtual_monitor(local); --} -- --static int ieee80211_stop(struct net_device *dev) --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- -- ieee80211_do_stop(sdata, true); -- -- return 0; --} -- --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, sdata_allmulti; -- -- allmulti = !!(dev->flags & IFF_ALLMULTI); -- sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); -- -- if (allmulti != sdata_allmulti) { -- if (dev->flags & IFF_ALLMULTI) -- atomic_inc(&local->iff_allmultis); -- else -- atomic_dec(&local->iff_allmultis); -- sdata->flags ^= IEEE80211_SDATA_ALLMULTI; -- } -- -- spin_lock_bh(&local->filter_lock); -- __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); -- spin_unlock_bh(&local->filter_lock); -- ieee80211_queue_work(&local->hw, &local->reconfig_filter); --} -- --/* -- * Called when the netdev is removed or, by the code below, before -- * the interface type changes. -- */ --static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) --{ -- int i; -- -- /* free extra data */ -- ieee80211_free_keys(sdata, false); -- -- ieee80211_debugfs_remove_netdev(sdata); -- -- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) -- __skb_queue_purge(&sdata->fragments[i].skb_list); -- sdata->fragment_next = 0; -- -- if (ieee80211_vif_is_mesh(&sdata->vif)) -- ieee80211_mesh_teardown_sdata(sdata); --} -- --static void ieee80211_uninit(struct net_device *dev) --{ -- ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); --} -- --#if LINUX_VERSION_IS_GEQ(5,2,0) --static u16 ieee80211_netdev_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- struct net_device *sb_dev) --#elif LINUX_VERSION_IS_GEQ(4,19,0) --static u16 ieee80211_netdev_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- struct net_device *sb_dev, -- select_queue_fallback_t fallback) --#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ -- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) --static u16 ieee80211_netdev_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- void *accel_priv, -- select_queue_fallback_t fallback) --#elif LINUX_VERSION_IS_GEQ(3,13,0) --static u16 ieee80211_netdev_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- void *accel_priv) --#else --static u16 ieee80211_netdev_select_queue(struct net_device *dev, -- struct sk_buff *skb) --#endif --{ -- return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); --} -- --static void --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(netdev_tstats(dev), 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; -- } --} --#if LINUX_VERSION_IS_LESS(4,11,0) --/* Just declare it here to keep sparse happy */ --struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, -- struct rtnl_link_stats64 *stats); --struct rtnl_link_stats64 * --bp_ieee80211_get_stats64(struct net_device *dev, -- struct rtnl_link_stats64 *stats){ -- ieee80211_get_stats64(dev, stats); -- return stats; --} --#endif -- --static const struct net_device_ops ieee80211_dataif_ops = { -- .ndo_open = ieee80211_open, -- .ndo_stop = ieee80211_stop, -- .ndo_uninit = ieee80211_uninit, -- .ndo_start_xmit = ieee80211_subif_start_xmit, -- .ndo_set_rx_mode = ieee80211_set_multicast_list, -- .ndo_set_mac_address = ieee80211_change_mac, -- .ndo_select_queue = ieee80211_netdev_select_queue, --#if LINUX_VERSION_IS_GEQ(4,11,0) -- .ndo_get_stats64 = ieee80211_get_stats64, --#else -- .ndo_get_stats64 = bp_ieee80211_get_stats64, --#endif -- --}; -- --#if LINUX_VERSION_IS_GEQ(5,2,0) --static u16 ieee80211_monitor_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- struct net_device *sb_dev) --#elif LINUX_VERSION_IS_GEQ(4,19,0) --static u16 ieee80211_monitor_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- struct net_device *sb_dev, -- select_queue_fallback_t fallback) --#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ -- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) --static u16 ieee80211_monitor_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- void *accel_priv, -- select_queue_fallback_t fallback) --#elif LINUX_VERSION_IS_GEQ(3,13,0) --static u16 ieee80211_monitor_select_queue(struct net_device *dev, -- struct sk_buff *skb, -- void *accel_priv) --#else --static u16 ieee80211_monitor_select_queue(struct net_device *dev, -- struct sk_buff *skb) --#endif --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- struct ieee80211_local *local = sdata->local; -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- struct ieee80211_hdr *hdr; -- int len_rthdr; -- -- if (local->hw.queues < IEEE80211_NUM_ACS) -- return 0; -- -- /* reset flags and info before parsing radiotap header */ -- memset(info, 0, sizeof(*info)); -- -- if (!ieee80211_parse_tx_radiotap(skb, dev)) -- return 0; /* doesn't matter, frame will be dropped */ -- -- len_rthdr = ieee80211_get_radiotap_len(skb->data); -- hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); -- if (skb->len < len_rthdr + 2 || -- skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control)) -- return 0; /* doesn't matter, frame will be dropped */ -- -- return ieee80211_select_queue_80211(sdata, skb, hdr); --} -- --static const struct net_device_ops ieee80211_monitorif_ops = { -- .ndo_open = ieee80211_open, -- .ndo_stop = ieee80211_stop, -- .ndo_uninit = ieee80211_uninit, -- .ndo_start_xmit = ieee80211_monitor_start_xmit, -- .ndo_set_rx_mode = ieee80211_set_multicast_list, -- .ndo_set_mac_address = ieee80211_change_mac, -- .ndo_select_queue = ieee80211_monitor_select_queue, --#if LINUX_VERSION_IS_GEQ(4,11,0) -- .ndo_get_stats64 = ieee80211_get_stats64, --#else -- .ndo_get_stats64 = bp_ieee80211_get_stats64, --#endif -- --}; -- --static const struct net_device_ops ieee80211_dataif_8023_ops = { -- .ndo_open = ieee80211_open, -- .ndo_stop = ieee80211_stop, -- .ndo_uninit = ieee80211_uninit, -- .ndo_start_xmit = ieee80211_subif_start_xmit_8023, -- .ndo_set_rx_mode = ieee80211_set_multicast_list, -- .ndo_set_mac_address = ieee80211_change_mac, -- .ndo_select_queue = ieee80211_netdev_select_queue, --#if LINUX_VERSION_IS_GEQ(4,11,0) -- .ndo_get_stats64 = ieee80211_get_stats64, --#else -- .ndo_get_stats64 = bp_ieee80211_get_stats64, --#endif -- --}; -- - static void ieee80211_if_free(struct net_device *dev) - { - free_percpu(netdev_tstats(dev)); -@@ -1408,32 +1432,6 @@ static void ieee80211_if_setup_no_queue( - #endif - } - --static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) --{ -- struct ieee80211_local *local = sdata->local; -- struct ieee80211_sub_if_data *bss = sdata; -- bool enabled; -- -- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { -- if (!sdata->bss) -- return; -- -- bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); -- } -- -- if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || -- !ieee80211_iftype_supports_encap_offload(bss->vif.type)) -- return; -- -- enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; -- if (sdata->wdev.use_4addr && -- !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) -- enabled = false; -- -- sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : -- &ieee80211_dataif_ops; --} -- - static void ieee80211_iface_work(struct work_struct *work) - { - struct ieee80211_sub_if_data *sdata = |