GNU Linux-libre 4.14.257-gnu1
[releases.git] / net / wireless / ocb.c
1 /*
2  * OCB mode implementation
3  *
4  * Copyright: (c) 2014 Czech Technical University in Prague
5  *            (c) 2014 Volkswagen Group Research
6  * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
7  * Funded by: Volkswagen Group Research
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include <linux/ieee80211.h>
15 #include <net/cfg80211.h>
16 #include "nl80211.h"
17 #include "core.h"
18 #include "rdev-ops.h"
19
20 int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
21                         struct net_device *dev,
22                         struct ocb_setup *setup)
23 {
24         struct wireless_dev *wdev = dev->ieee80211_ptr;
25         int err;
26
27         ASSERT_WDEV_LOCK(wdev);
28
29         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
30                 return -EOPNOTSUPP;
31
32         if (!rdev->ops->join_ocb)
33                 return -EOPNOTSUPP;
34
35         if (WARN_ON(!setup->chandef.chan))
36                 return -EINVAL;
37
38         err = rdev_join_ocb(rdev, dev, setup);
39         if (!err)
40                 wdev->chandef = setup->chandef;
41
42         return err;
43 }
44
45 int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
46                       struct net_device *dev,
47                       struct ocb_setup *setup)
48 {
49         struct wireless_dev *wdev = dev->ieee80211_ptr;
50         int err;
51
52         wdev_lock(wdev);
53         err = __cfg80211_join_ocb(rdev, dev, setup);
54         wdev_unlock(wdev);
55
56         return err;
57 }
58
59 int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
60                          struct net_device *dev)
61 {
62         struct wireless_dev *wdev = dev->ieee80211_ptr;
63         int err;
64
65         ASSERT_WDEV_LOCK(wdev);
66
67         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
68                 return -EOPNOTSUPP;
69
70         if (!rdev->ops->leave_ocb)
71                 return -EOPNOTSUPP;
72
73         err = rdev_leave_ocb(rdev, dev);
74         if (!err)
75                 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
76
77         return err;
78 }
79
80 int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
81                        struct net_device *dev)
82 {
83         struct wireless_dev *wdev = dev->ieee80211_ptr;
84         int err;
85
86         wdev_lock(wdev);
87         err = __cfg80211_leave_ocb(rdev, dev);
88         wdev_unlock(wdev);
89
90         return err;
91 }