xref: /openbmc/linux/net/wireless/ap.c (revision cba7217a)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
27b0a0e3cSJohannes Berg /*
37b0a0e3cSJohannes Berg  * Parts of this file are
47b0a0e3cSJohannes Berg  * Copyright (C) 2022 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 
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 
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)
42*cba7217aSAlvin Š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)557b0a0e3cSJohannes 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 }
757b0a0e3cSJohannes Berg 
cfg80211_stop_ap(struct cfg80211_registered_device * rdev,struct net_device * dev,int link_id,bool notify)7660771780SMichal Kazior int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
777b0a0e3cSJohannes Berg 		     struct net_device *dev, int link_id,
787b0a0e3cSJohannes 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);
847b0a0e3cSJohannes Berg 	err = __cfg80211_stop_ap(rdev, dev, link_id, notify);
8560771780SMichal Kazior 	wdev_unlock(wdev);
8660771780SMichal Kazior 
8760771780SMichal Kazior 	return err;
8860771780SMichal Kazior }
89