xref: /openbmc/linux/net/wireless/ocb.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
26e0bd6c3SRostislav Lisovy /*
36e0bd6c3SRostislav Lisovy  * OCB mode implementation
46e0bd6c3SRostislav Lisovy  *
56e0bd6c3SRostislav Lisovy  * Copyright: (c) 2014 Czech Technical University in Prague
66e0bd6c3SRostislav Lisovy  *            (c) 2014 Volkswagen Group Research
77b0a0e3cSJohannes Berg  * Copyright (C) 2022 Intel Corporation
86e0bd6c3SRostislav Lisovy  * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
96e0bd6c3SRostislav Lisovy  * Funded by: Volkswagen Group Research
106e0bd6c3SRostislav Lisovy  */
116e0bd6c3SRostislav Lisovy 
126e0bd6c3SRostislav Lisovy #include <linux/ieee80211.h>
136e0bd6c3SRostislav Lisovy #include <net/cfg80211.h>
146e0bd6c3SRostislav Lisovy #include "nl80211.h"
156e0bd6c3SRostislav Lisovy #include "core.h"
166e0bd6c3SRostislav Lisovy #include "rdev-ops.h"
176e0bd6c3SRostislav Lisovy 
__cfg80211_join_ocb(struct cfg80211_registered_device * rdev,struct net_device * dev,struct ocb_setup * setup)186e0bd6c3SRostislav Lisovy int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
196e0bd6c3SRostislav Lisovy 			struct net_device *dev,
206e0bd6c3SRostislav Lisovy 			struct ocb_setup *setup)
216e0bd6c3SRostislav Lisovy {
226e0bd6c3SRostislav Lisovy 	struct wireless_dev *wdev = dev->ieee80211_ptr;
236e0bd6c3SRostislav Lisovy 	int err;
246e0bd6c3SRostislav Lisovy 
256e0bd6c3SRostislav Lisovy 	ASSERT_WDEV_LOCK(wdev);
266e0bd6c3SRostislav Lisovy 
276e0bd6c3SRostislav Lisovy 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
286e0bd6c3SRostislav Lisovy 		return -EOPNOTSUPP;
296e0bd6c3SRostislav Lisovy 
301b9df2d2SOla Olsson 	if (!rdev->ops->join_ocb)
311b9df2d2SOla Olsson 		return -EOPNOTSUPP;
321b9df2d2SOla Olsson 
336e0bd6c3SRostislav Lisovy 	if (WARN_ON(!setup->chandef.chan))
346e0bd6c3SRostislav Lisovy 		return -EINVAL;
356e0bd6c3SRostislav Lisovy 
366e0bd6c3SRostislav Lisovy 	err = rdev_join_ocb(rdev, dev, setup);
376e0bd6c3SRostislav Lisovy 	if (!err)
387b0a0e3cSJohannes Berg 		wdev->u.ocb.chandef = setup->chandef;
396e0bd6c3SRostislav Lisovy 
406e0bd6c3SRostislav Lisovy 	return err;
416e0bd6c3SRostislav Lisovy }
426e0bd6c3SRostislav Lisovy 
cfg80211_join_ocb(struct cfg80211_registered_device * rdev,struct net_device * dev,struct ocb_setup * setup)436e0bd6c3SRostislav Lisovy int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
446e0bd6c3SRostislav Lisovy 		      struct net_device *dev,
456e0bd6c3SRostislav Lisovy 		      struct ocb_setup *setup)
466e0bd6c3SRostislav Lisovy {
476e0bd6c3SRostislav Lisovy 	struct wireless_dev *wdev = dev->ieee80211_ptr;
486e0bd6c3SRostislav Lisovy 	int err;
496e0bd6c3SRostislav Lisovy 
506e0bd6c3SRostislav Lisovy 	wdev_lock(wdev);
516e0bd6c3SRostislav Lisovy 	err = __cfg80211_join_ocb(rdev, dev, setup);
526e0bd6c3SRostislav Lisovy 	wdev_unlock(wdev);
536e0bd6c3SRostislav Lisovy 
546e0bd6c3SRostislav Lisovy 	return err;
556e0bd6c3SRostislav Lisovy }
566e0bd6c3SRostislav Lisovy 
__cfg80211_leave_ocb(struct cfg80211_registered_device * rdev,struct net_device * dev)576e0bd6c3SRostislav Lisovy int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
586e0bd6c3SRostislav Lisovy 			 struct net_device *dev)
596e0bd6c3SRostislav Lisovy {
606e0bd6c3SRostislav Lisovy 	struct wireless_dev *wdev = dev->ieee80211_ptr;
616e0bd6c3SRostislav Lisovy 	int err;
626e0bd6c3SRostislav Lisovy 
636e0bd6c3SRostislav Lisovy 	ASSERT_WDEV_LOCK(wdev);
646e0bd6c3SRostislav Lisovy 
656e0bd6c3SRostislav Lisovy 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
666e0bd6c3SRostislav Lisovy 		return -EOPNOTSUPP;
676e0bd6c3SRostislav Lisovy 
686e0bd6c3SRostislav Lisovy 	if (!rdev->ops->leave_ocb)
696e0bd6c3SRostislav Lisovy 		return -EOPNOTSUPP;
706e0bd6c3SRostislav Lisovy 
71*abc76cf5SJohannes Berg 	if (!wdev->u.ocb.chandef.chan)
72*abc76cf5SJohannes Berg 		return -ENOTCONN;
73*abc76cf5SJohannes Berg 
746e0bd6c3SRostislav Lisovy 	err = rdev_leave_ocb(rdev, dev);
756e0bd6c3SRostislav Lisovy 	if (!err)
767b0a0e3cSJohannes Berg 		memset(&wdev->u.ocb.chandef, 0, sizeof(wdev->u.ocb.chandef));
776e0bd6c3SRostislav Lisovy 
786e0bd6c3SRostislav Lisovy 	return err;
796e0bd6c3SRostislav Lisovy }
806e0bd6c3SRostislav Lisovy 
cfg80211_leave_ocb(struct cfg80211_registered_device * rdev,struct net_device * dev)816e0bd6c3SRostislav Lisovy int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
826e0bd6c3SRostislav Lisovy 		       struct net_device *dev)
836e0bd6c3SRostislav Lisovy {
846e0bd6c3SRostislav Lisovy 	struct wireless_dev *wdev = dev->ieee80211_ptr;
856e0bd6c3SRostislav Lisovy 	int err;
866e0bd6c3SRostislav Lisovy 
876e0bd6c3SRostislav Lisovy 	wdev_lock(wdev);
886e0bd6c3SRostislav Lisovy 	err = __cfg80211_leave_ocb(rdev, dev);
896e0bd6c3SRostislav Lisovy 	wdev_unlock(wdev);
906e0bd6c3SRostislav Lisovy 
916e0bd6c3SRostislav Lisovy 	return err;
926e0bd6c3SRostislav Lisovy }
93