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