1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
27b0a0e3cSJohannes Berg /*
37b0a0e3cSJohannes Berg * Parts of this file are
4*076fc877SJohannes Berg * Copyright (C) 2022-2023 Intel Corporation
57b0a0e3cSJohannes Berg */
660771780SMichal Kazior #include <linux/ieee80211.h>
760771780SMichal Kazior #include <linux/export.h>
860771780SMichal Kazior #include <net/cfg80211.h>
960771780SMichal Kazior #include "nl80211.h"
1060771780SMichal Kazior #include "core.h"
11e35e4d28SHila Gonen #include "rdev-ops.h"
1260771780SMichal Kazior
1360771780SMichal Kazior
___cfg80211_stop_ap(struct cfg80211_registered_device * rdev,struct net_device * dev,unsigned int link_id,bool notify)147b0a0e3cSJohannes Berg static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
157b0a0e3cSJohannes Berg struct net_device *dev, unsigned int link_id,
167b0a0e3cSJohannes Berg bool notify)
1760771780SMichal Kazior {
1860771780SMichal Kazior struct wireless_dev *wdev = dev->ieee80211_ptr;
1960771780SMichal Kazior int err;
2060771780SMichal Kazior
21*076fc877SJohannes Berg lockdep_assert_wiphy(wdev->wiphy);
2260771780SMichal Kazior
2360771780SMichal Kazior if (!rdev->ops->stop_ap)
2460771780SMichal Kazior return -EOPNOTSUPP;
2560771780SMichal Kazior
2660771780SMichal Kazior if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
2760771780SMichal Kazior dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2860771780SMichal Kazior return -EOPNOTSUPP;
2960771780SMichal Kazior
307b0a0e3cSJohannes Berg if (!wdev->links[link_id].ap.beacon_interval)
3160771780SMichal Kazior return -ENOENT;
3260771780SMichal Kazior
337b0a0e3cSJohannes Berg err = rdev_stop_ap(rdev, dev, link_id);
34f4489ebeSMichal Kazior if (!err) {
35466a3061SDenis Kenzior wdev->conn_owner_nlportid = 0;
367b0a0e3cSJohannes Berg wdev->links[link_id].ap.beacon_interval = 0;
377b0a0e3cSJohannes Berg memset(&wdev->links[link_id].ap.chandef, 0,
387b0a0e3cSJohannes Berg sizeof(wdev->links[link_id].ap.chandef));
397b0a0e3cSJohannes Berg wdev->u.ap.ssid_len = 0;
40fa9ffc74SKyeyoon Park rdev_set_qos_map(rdev, dev, NULL);
417c8d5e03SIlan Peer if (notify)
42cba7217aSAlvin Šipraga nl80211_send_ap_stopped(wdev, link_id);
43b35a51c7SVasanthakumar Thiagarajan
44b35a51c7SVasanthakumar Thiagarajan /* Should we apply the grace period during beaconing interface
45b35a51c7SVasanthakumar Thiagarajan * shutdown also?
46b35a51c7SVasanthakumar Thiagarajan */
47b35a51c7SVasanthakumar Thiagarajan cfg80211_sched_dfs_chan_update(rdev);
48f4489ebeSMichal Kazior }
4960771780SMichal Kazior
50e005bd7dSJohannes Berg schedule_work(&cfg80211_disconnect_work);
51e005bd7dSJohannes Berg
5260771780SMichal Kazior return err;
5360771780SMichal Kazior }
5460771780SMichal Kazior
cfg80211_stop_ap(struct cfg80211_registered_device * rdev,struct net_device * dev,int link_id,bool notify)55*076fc877SJohannes Berg int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
567b0a0e3cSJohannes Berg struct net_device *dev, int link_id,
577b0a0e3cSJohannes Berg bool notify)
587b0a0e3cSJohannes Berg {
597b0a0e3cSJohannes Berg unsigned int link;
607b0a0e3cSJohannes Berg int ret = 0;
617b0a0e3cSJohannes Berg
627b0a0e3cSJohannes Berg if (link_id >= 0)
637b0a0e3cSJohannes Berg return ___cfg80211_stop_ap(rdev, dev, link_id, notify);
647b0a0e3cSJohannes Berg
657b0a0e3cSJohannes Berg for_each_valid_link(dev->ieee80211_ptr, link) {
667b0a0e3cSJohannes Berg int ret1 = ___cfg80211_stop_ap(rdev, dev, link, notify);
677b0a0e3cSJohannes Berg
687b0a0e3cSJohannes Berg if (ret1)
697b0a0e3cSJohannes Berg ret = ret1;
707b0a0e3cSJohannes Berg /* try the next one also if one errored */
717b0a0e3cSJohannes Berg }
727b0a0e3cSJohannes Berg
737b0a0e3cSJohannes Berg return ret;
747b0a0e3cSJohannes Berg }
75