Merge tag 'perf-tools-for-v6.2-1-2022-12-16' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / net / wireless / ap.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Parts of this file are
4  * Copyright (C) 2022 Intel Corporation
5  */
6 #include <linux/ieee80211.h>
7 #include <linux/export.h>
8 #include <net/cfg80211.h>
9 #include "nl80211.h"
10 #include "core.h"
11 #include "rdev-ops.h"
12
13
14 static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
15                                struct net_device *dev, unsigned int link_id,
16                                bool notify)
17 {
18         struct wireless_dev *wdev = dev->ieee80211_ptr;
19         int err;
20
21         ASSERT_WDEV_LOCK(wdev);
22
23         if (!rdev->ops->stop_ap)
24                 return -EOPNOTSUPP;
25
26         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
27             dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
28                 return -EOPNOTSUPP;
29
30         if (!wdev->links[link_id].ap.beacon_interval)
31                 return -ENOENT;
32
33         err = rdev_stop_ap(rdev, dev, link_id);
34         if (!err) {
35                 wdev->conn_owner_nlportid = 0;
36                 wdev->links[link_id].ap.beacon_interval = 0;
37                 memset(&wdev->links[link_id].ap.chandef, 0,
38                        sizeof(wdev->links[link_id].ap.chandef));
39                 wdev->u.ap.ssid_len = 0;
40                 rdev_set_qos_map(rdev, dev, NULL);
41                 if (notify)
42                         nl80211_send_ap_stopped(wdev);
43
44                 /* Should we apply the grace period during beaconing interface
45                  * shutdown also?
46                  */
47                 cfg80211_sched_dfs_chan_update(rdev);
48         }
49
50         schedule_work(&cfg80211_disconnect_work);
51
52         return err;
53 }
54
55 int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
56                        struct net_device *dev, int link_id,
57                        bool notify)
58 {
59         unsigned int link;
60         int ret = 0;
61
62         if (link_id >= 0)
63                 return ___cfg80211_stop_ap(rdev, dev, link_id, notify);
64
65         for_each_valid_link(dev->ieee80211_ptr, link) {
66                 int ret1 = ___cfg80211_stop_ap(rdev, dev, link, notify);
67
68                 if (ret1)
69                         ret = ret1;
70                 /* try the next one also if one errored */
71         }
72
73         return ret;
74 }
75
76 int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
77                      struct net_device *dev, int link_id,
78                      bool notify)
79 {
80         struct wireless_dev *wdev = dev->ieee80211_ptr;
81         int err;
82
83         wdev_lock(wdev);
84         err = __cfg80211_stop_ap(rdev, dev, link_id, notify);
85         wdev_unlock(wdev);
86
87         return err;
88 }