GNU Linux-libre 6.8.9-gnu
[releases.git] / net / wireless / ap.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Parts of this file are
4  * Copyright (C) 2022-2023 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         lockdep_assert_wiphy(wdev->wiphy);
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, link_id);
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 }