xref: /openbmc/linux/net/wireless/ap.c (revision 7b0a0e3c)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2*7b0a0e3cSJohannes Berg /*
3*7b0a0e3cSJohannes Berg  * Parts of this file are
4*7b0a0e3cSJohannes Berg  * Copyright (C) 2022 Intel Corporation
5*7b0a0e3cSJohannes 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 
14*7b0a0e3cSJohannes Berg static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
15*7b0a0e3cSJohannes Berg 			       struct net_device *dev, unsigned int link_id,
16*7b0a0e3cSJohannes Berg 			       bool notify)
1760771780SMichal Kazior {
1860771780SMichal Kazior 	struct wireless_dev *wdev = dev->ieee80211_ptr;
1960771780SMichal Kazior 	int err;
2060771780SMichal Kazior 
2160771780SMichal Kazior 	ASSERT_WDEV_LOCK(wdev);
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 
30*7b0a0e3cSJohannes Berg 	if (!wdev->links[link_id].ap.beacon_interval)
3160771780SMichal Kazior 		return -ENOENT;
3260771780SMichal Kazior 
33*7b0a0e3cSJohannes Berg 	err = rdev_stop_ap(rdev, dev, link_id);
34f4489ebeSMichal Kazior 	if (!err) {
35466a3061SDenis Kenzior 		wdev->conn_owner_nlportid = 0;
36*7b0a0e3cSJohannes Berg 		wdev->links[link_id].ap.beacon_interval = 0;
37*7b0a0e3cSJohannes Berg 		memset(&wdev->links[link_id].ap.chandef, 0,
38*7b0a0e3cSJohannes Berg 		       sizeof(wdev->links[link_id].ap.chandef));
39*7b0a0e3cSJohannes Berg 		wdev->u.ap.ssid_len = 0;
40fa9ffc74SKyeyoon Park 		rdev_set_qos_map(rdev, dev, NULL);
417c8d5e03SIlan Peer 		if (notify)
42348baf0eSJohannes Berg 			nl80211_send_ap_stopped(wdev);
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 
55*7b0a0e3cSJohannes Berg int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
56*7b0a0e3cSJohannes Berg 		       struct net_device *dev, int link_id,
57*7b0a0e3cSJohannes Berg 		       bool notify)
58*7b0a0e3cSJohannes Berg {
59*7b0a0e3cSJohannes Berg 	unsigned int link;
60*7b0a0e3cSJohannes Berg 	int ret = 0;
61*7b0a0e3cSJohannes Berg 
62*7b0a0e3cSJohannes Berg 	if (link_id >= 0)
63*7b0a0e3cSJohannes Berg 		return ___cfg80211_stop_ap(rdev, dev, link_id, notify);
64*7b0a0e3cSJohannes Berg 
65*7b0a0e3cSJohannes Berg 	for_each_valid_link(dev->ieee80211_ptr, link) {
66*7b0a0e3cSJohannes Berg 		int ret1 = ___cfg80211_stop_ap(rdev, dev, link, notify);
67*7b0a0e3cSJohannes Berg 
68*7b0a0e3cSJohannes Berg 		if (ret1)
69*7b0a0e3cSJohannes Berg 			ret = ret1;
70*7b0a0e3cSJohannes Berg 		/* try the next one also if one errored */
71*7b0a0e3cSJohannes Berg 	}
72*7b0a0e3cSJohannes Berg 
73*7b0a0e3cSJohannes Berg 	return ret;
74*7b0a0e3cSJohannes Berg }
75*7b0a0e3cSJohannes Berg 
7660771780SMichal Kazior int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
77*7b0a0e3cSJohannes Berg 		     struct net_device *dev, int link_id,
78*7b0a0e3cSJohannes Berg 		     bool notify)
7960771780SMichal Kazior {
8060771780SMichal Kazior 	struct wireless_dev *wdev = dev->ieee80211_ptr;
8160771780SMichal Kazior 	int err;
8260771780SMichal Kazior 
8360771780SMichal Kazior 	wdev_lock(wdev);
84*7b0a0e3cSJohannes Berg 	err = __cfg80211_stop_ap(rdev, dev, link_id, notify);
8560771780SMichal Kazior 	wdev_unlock(wdev);
8660771780SMichal Kazior 
8760771780SMichal Kazior 	return err;
8860771780SMichal Kazior }
89