generic: add more missing linux 4.1 symbols
[librecmc/librecmc.git] / package / kernel / mac80211 / patches / 308-cfg80211-use-RTNL-locked-reg_can_beacon-for-IR-relax.patch
1 From: Arik Nemtsov <arik@wizery.com>
2 Date: Wed, 8 Jul 2015 15:41:44 +0300
3 Subject: [PATCH] cfg80211: use RTNL locked reg_can_beacon for IR-relaxation
4
5 The RTNL is required to check for IR-relaxation conditions that allow
6 more channels to beacon. Export an RTNL locked version of reg_can_beacon
7 and use it where possible in AP/STA interface type flows, where
8 IR-relaxation may be applicable.
9
10 Fixes: 06f207fc5418 ("cfg80211: change GO_CONCURRENT to IR_CONCURRENT for STA")
11 Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
12 Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
13 ---
14
15 --- a/include/net/cfg80211.h
16 +++ b/include/net/cfg80211.h
17 @@ -4871,6 +4871,23 @@ bool cfg80211_reg_can_beacon(struct wiph
18                              struct cfg80211_chan_def *chandef,
19                              enum nl80211_iftype iftype);
20  
21 +/**
22 + * cfg80211_reg_can_beacon_relax - check if beaconing is allowed with relaxation
23 + * @wiphy: the wiphy
24 + * @chandef: the channel definition
25 + * @iftype: interface type
26 + *
27 + * Return: %true if there is no secondary channel or the secondary channel(s)
28 + * can be used for beaconing (i.e. is not a radar channel etc.). This version
29 + * also checks if IR-relaxation conditions apply, to allow beaconing under
30 + * more permissive conditions.
31 + *
32 + * Requires the RTNL to be held.
33 + */
34 +bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
35 +                                  struct cfg80211_chan_def *chandef,
36 +                                  enum nl80211_iftype iftype);
37 +
38  /*
39   * cfg80211_ch_switch_notify - update wdev channel and notify userspace
40   * @dev: the device which switched channels
41 --- a/net/mac80211/tdls.c
42 +++ b/net/mac80211/tdls.c
43 @@ -69,6 +69,7 @@ ieee80211_tdls_add_subband(struct ieee80
44         struct ieee80211_channel *ch;
45         struct cfg80211_chan_def chandef;
46         int i, subband_start;
47 +       struct wiphy *wiphy = sdata->local->hw.wiphy;
48  
49         for (i = start; i <= end; i += spacing) {
50                 if (!ch_cnt)
51 @@ -79,9 +80,8 @@ ieee80211_tdls_add_subband(struct ieee80
52                         /* we will be active on the channel */
53                         cfg80211_chandef_create(&chandef, ch,
54                                                 NL80211_CHAN_NO_HT);
55 -                       if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy,
56 -                                                   &chandef,
57 -                                                   sdata->wdev.iftype)) {
58 +                       if (cfg80211_reg_can_beacon_relax(wiphy, &chandef,
59 +                                                         sdata->wdev.iftype)) {
60                                 ch_cnt++;
61                                 /*
62                                  * check if the next channel is also part of
63 --- a/net/wireless/chan.c
64 +++ b/net/wireless/chan.c
65 @@ -797,23 +797,18 @@ static bool cfg80211_ir_permissive_chan(
66         return false;
67  }
68  
69 -bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
70 -                            struct cfg80211_chan_def *chandef,
71 -                            enum nl80211_iftype iftype)
72 +static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
73 +                                    struct cfg80211_chan_def *chandef,
74 +                                    enum nl80211_iftype iftype,
75 +                                    bool check_no_ir)
76  {
77         bool res;
78         u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
79                                IEEE80211_CHAN_RADAR;
80  
81 -       trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype);
82 +       trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
83  
84 -       /*
85 -        * Under certain conditions suggested by some regulatory bodies a
86 -        * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
87 -        * only if such relaxations are not enabled and the conditions are not
88 -        * met.
89 -        */
90 -       if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan))
91 +       if (check_no_ir)
92                 prohibited_flags |= IEEE80211_CHAN_NO_IR;
93  
94         if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
95 @@ -827,8 +822,36 @@ bool cfg80211_reg_can_beacon(struct wiph
96         trace_cfg80211_return_bool(res);
97         return res;
98  }
99 +
100 +bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
101 +                            struct cfg80211_chan_def *chandef,
102 +                            enum nl80211_iftype iftype)
103 +{
104 +       return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
105 +}
106  EXPORT_SYMBOL(cfg80211_reg_can_beacon);
107  
108 +bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
109 +                                  struct cfg80211_chan_def *chandef,
110 +                                  enum nl80211_iftype iftype)
111 +{
112 +       bool check_no_ir;
113 +
114 +       ASSERT_RTNL();
115 +
116 +       /*
117 +        * Under certain conditions suggested by some regulatory bodies a
118 +        * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
119 +        * only if such relaxations are not enabled and the conditions are not
120 +        * met.
121 +        */
122 +       check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
123 +                                                  chandef->chan);
124 +
125 +       return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
126 +}
127 +EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);
128 +
129  int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
130                                  struct cfg80211_chan_def *chandef)
131  {
132 --- a/net/wireless/nl80211.c
133 +++ b/net/wireless/nl80211.c
134 @@ -2007,7 +2007,8 @@ static int __nl80211_set_channel(struct
135         switch (iftype) {
136         case NL80211_IFTYPE_AP:
137         case NL80211_IFTYPE_P2P_GO:
138 -               if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) {
139 +               if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
140 +                                                  iftype)) {
141                         result = -EINVAL;
142                         break;
143                 }
144 @@ -3408,8 +3409,8 @@ static int nl80211_start_ap(struct sk_bu
145         } else if (!nl80211_get_ap_channel(rdev, &params))
146                 return -EINVAL;
147  
148 -       if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef,
149 -                                    wdev->iftype))
150 +       if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
151 +                                          wdev->iftype))
152                 return -EINVAL;
153  
154         if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
155 @@ -6500,8 +6501,8 @@ skip_beacons:
156         if (err)
157                 return err;
158  
159 -       if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef,
160 -                                    wdev->iftype))
161 +       if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
162 +                                          wdev->iftype))
163                 return -EINVAL;
164  
165         err = cfg80211_chandef_dfs_required(wdev->wiphy,
166 @@ -10188,7 +10189,8 @@ static int nl80211_tdls_channel_switch(s
167                 return -EINVAL;
168  
169         /* we will be active on the TDLS link */
170 -       if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
171 +       if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
172 +                                          wdev->iftype))
173                 return -EINVAL;
174  
175         /* don't allow switching to DFS channels */
176 --- a/net/wireless/reg.c
177 +++ b/net/wireless/reg.c
178 @@ -1589,7 +1589,7 @@ static bool reg_wdev_chan_valid(struct w
179         case NL80211_IFTYPE_AP:
180         case NL80211_IFTYPE_P2P_GO:
181         case NL80211_IFTYPE_ADHOC:
182 -               return cfg80211_reg_can_beacon(wiphy, &chandef, iftype);
183 +               return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
184         case NL80211_IFTYPE_STATION:
185         case NL80211_IFTYPE_P2P_CLIENT:
186                 return cfg80211_chandef_usable(wiphy, &chandef,
187 --- a/net/wireless/trace.h
188 +++ b/net/wireless/trace.h
189 @@ -2358,20 +2358,23 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify,
190  
191  TRACE_EVENT(cfg80211_reg_can_beacon,
192         TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
193 -                enum nl80211_iftype iftype),
194 -       TP_ARGS(wiphy, chandef, iftype),
195 +                enum nl80211_iftype iftype, bool check_no_ir),
196 +       TP_ARGS(wiphy, chandef, iftype, check_no_ir),
197         TP_STRUCT__entry(
198                 WIPHY_ENTRY
199                 CHAN_DEF_ENTRY
200                 __field(enum nl80211_iftype, iftype)
201 +               __field(bool, check_no_ir)
202         ),
203         TP_fast_assign(
204                 WIPHY_ASSIGN;
205                 CHAN_DEF_ASSIGN(chandef);
206                 __entry->iftype = iftype;
207 +               __entry->check_no_ir = check_no_ir;
208         ),
209 -       TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d",
210 -                 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype)
211 +       TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d check_no_ir=%s",
212 +                 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype,
213 +                 BOOL_TO_STR(__entry->check_no_ir))
214  );
215  
216  TRACE_EVENT(cfg80211_chandef_dfs_required,