1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
4 #include <linux/nl80211.h>
6 #include "qlink_util.h"
8 u16
qlink_iface_type_to_nl_mask(u16 qlink_type
)
14 result
|= BIT(NL80211_IFTYPE_AP
);
16 case QLINK_IFTYPE_STATION
:
17 result
|= BIT(NL80211_IFTYPE_STATION
);
19 case QLINK_IFTYPE_ADHOC
:
20 result
|= BIT(NL80211_IFTYPE_ADHOC
);
22 case QLINK_IFTYPE_MONITOR
:
23 result
|= BIT(NL80211_IFTYPE_MONITOR
);
25 case QLINK_IFTYPE_WDS
:
26 result
|= BIT(NL80211_IFTYPE_WDS
);
28 case QLINK_IFTYPE_AP_VLAN
:
29 result
|= BIT(NL80211_IFTYPE_AP_VLAN
);
36 u8
qlink_chan_width_mask_to_nl(u16 qlink_mask
)
40 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_5
))
41 result
|= BIT(NL80211_CHAN_WIDTH_5
);
43 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_10
))
44 result
|= BIT(NL80211_CHAN_WIDTH_10
);
46 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_20_NOHT
))
47 result
|= BIT(NL80211_CHAN_WIDTH_20_NOHT
);
49 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_20
))
50 result
|= BIT(NL80211_CHAN_WIDTH_20
);
52 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_40
))
53 result
|= BIT(NL80211_CHAN_WIDTH_40
);
55 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_80
))
56 result
|= BIT(NL80211_CHAN_WIDTH_80
);
58 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_80P80
))
59 result
|= BIT(NL80211_CHAN_WIDTH_80P80
);
61 if (qlink_mask
& BIT(QLINK_CHAN_WIDTH_160
))
62 result
|= BIT(NL80211_CHAN_WIDTH_160
);
67 static enum nl80211_chan_width
qlink_chanwidth_to_nl(u8 qlw
)
70 case QLINK_CHAN_WIDTH_20_NOHT
:
71 return NL80211_CHAN_WIDTH_20_NOHT
;
72 case QLINK_CHAN_WIDTH_20
:
73 return NL80211_CHAN_WIDTH_20
;
74 case QLINK_CHAN_WIDTH_40
:
75 return NL80211_CHAN_WIDTH_40
;
76 case QLINK_CHAN_WIDTH_80
:
77 return NL80211_CHAN_WIDTH_80
;
78 case QLINK_CHAN_WIDTH_80P80
:
79 return NL80211_CHAN_WIDTH_80P80
;
80 case QLINK_CHAN_WIDTH_160
:
81 return NL80211_CHAN_WIDTH_160
;
82 case QLINK_CHAN_WIDTH_5
:
83 return NL80211_CHAN_WIDTH_5
;
84 case QLINK_CHAN_WIDTH_10
:
85 return NL80211_CHAN_WIDTH_10
;
91 static u8
qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth
)
94 case NL80211_CHAN_WIDTH_20_NOHT
:
95 return QLINK_CHAN_WIDTH_20_NOHT
;
96 case NL80211_CHAN_WIDTH_20
:
97 return QLINK_CHAN_WIDTH_20
;
98 case NL80211_CHAN_WIDTH_40
:
99 return QLINK_CHAN_WIDTH_40
;
100 case NL80211_CHAN_WIDTH_80
:
101 return QLINK_CHAN_WIDTH_80
;
102 case NL80211_CHAN_WIDTH_80P80
:
103 return QLINK_CHAN_WIDTH_80P80
;
104 case NL80211_CHAN_WIDTH_160
:
105 return QLINK_CHAN_WIDTH_160
;
106 case NL80211_CHAN_WIDTH_5
:
107 return QLINK_CHAN_WIDTH_5
;
108 case NL80211_CHAN_WIDTH_10
:
109 return QLINK_CHAN_WIDTH_10
;
115 void qlink_chandef_q2cfg(struct wiphy
*wiphy
,
116 const struct qlink_chandef
*qch
,
117 struct cfg80211_chan_def
*chdef
)
119 struct ieee80211_channel
*chan
;
121 chan
= ieee80211_get_channel(wiphy
, le16_to_cpu(qch
->chan
.center_freq
));
124 chdef
->center_freq1
= le16_to_cpu(qch
->center_freq1
);
125 chdef
->center_freq2
= le16_to_cpu(qch
->center_freq2
);
126 chdef
->width
= qlink_chanwidth_to_nl(qch
->width
);
129 void qlink_chandef_cfg2q(const struct cfg80211_chan_def
*chdef
,
130 struct qlink_chandef
*qch
)
132 struct ieee80211_channel
*chan
= chdef
->chan
;
134 qch
->chan
.hw_value
= cpu_to_le16(chan
->hw_value
);
135 qch
->chan
.center_freq
= cpu_to_le16(chan
->center_freq
);
136 qch
->chan
.flags
= cpu_to_le32(chan
->flags
);
138 qch
->center_freq1
= cpu_to_le16(chdef
->center_freq1
);
139 qch
->center_freq2
= cpu_to_le16(chdef
->center_freq2
);
140 qch
->width
= qlink_chanwidth_nl_to_qlink(chdef
->width
);
143 enum qlink_hidden_ssid
qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val
)
146 case NL80211_HIDDEN_SSID_ZERO_LEN
:
147 return QLINK_HIDDEN_SSID_ZERO_LEN
;
148 case NL80211_HIDDEN_SSID_ZERO_CONTENTS
:
149 return QLINK_HIDDEN_SSID_ZERO_CONTENTS
;
150 case NL80211_HIDDEN_SSID_NOT_IN_USE
:
152 return QLINK_HIDDEN_SSID_NOT_IN_USE
;
156 bool qtnf_utils_is_bit_set(const u8
*arr
, unsigned int bit
,
157 unsigned int arr_max_len
)
159 unsigned int idx
= bit
/ BITS_PER_BYTE
;
160 u8 mask
= 1 << (bit
- (idx
* BITS_PER_BYTE
));
162 if (idx
>= arr_max_len
)
165 return arr
[idx
] & mask
;
168 void qlink_acl_data_cfg2q(const struct cfg80211_acl_data
*acl
,
169 struct qlink_acl_data
*qacl
)
171 switch (acl
->acl_policy
) {
172 case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED
:
174 cpu_to_le32(QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED
);
176 case NL80211_ACL_POLICY_DENY_UNLESS_LISTED
:
177 qacl
->policy
= cpu_to_le32(QLINK_ACL_POLICY_DENY_UNLESS_LISTED
);
181 qacl
->num_entries
= cpu_to_le32(acl
->n_acl_entries
);
182 memcpy(qacl
->mac_addrs
, acl
->mac_addrs
,
183 acl
->n_acl_entries
* sizeof(*qacl
->mac_addrs
));
186 enum qlink_band
qlink_utils_band_cfg2q(enum nl80211_band band
)
189 case NL80211_BAND_2GHZ
:
190 return QLINK_BAND_2GHZ
;
191 case NL80211_BAND_5GHZ
:
192 return QLINK_BAND_5GHZ
;
193 case NL80211_BAND_60GHZ
:
194 return QLINK_BAND_60GHZ
;
200 enum qlink_dfs_state
qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state
)
203 case NL80211_DFS_USABLE
:
204 return QLINK_DFS_USABLE
;
205 case NL80211_DFS_AVAILABLE
:
206 return QLINK_DFS_AVAILABLE
;
207 case NL80211_DFS_UNAVAILABLE
:
209 return QLINK_DFS_UNAVAILABLE
;
213 u32
qlink_utils_chflags_cfg2q(u32 cfgflags
)
217 if (cfgflags
& IEEE80211_CHAN_DISABLED
)
218 flags
|= QLINK_CHAN_DISABLED
;
220 if (cfgflags
& IEEE80211_CHAN_NO_IR
)
221 flags
|= QLINK_CHAN_NO_IR
;
223 if (cfgflags
& IEEE80211_CHAN_RADAR
)
224 flags
|= QLINK_CHAN_RADAR
;
226 if (cfgflags
& IEEE80211_CHAN_NO_HT40PLUS
)
227 flags
|= QLINK_CHAN_NO_HT40PLUS
;
229 if (cfgflags
& IEEE80211_CHAN_NO_HT40MINUS
)
230 flags
|= QLINK_CHAN_NO_HT40MINUS
;
232 if (cfgflags
& IEEE80211_CHAN_NO_80MHZ
)
233 flags
|= QLINK_CHAN_NO_80MHZ
;
235 if (cfgflags
& IEEE80211_CHAN_NO_160MHZ
)
236 flags
|= QLINK_CHAN_NO_160MHZ
;
241 static u32
qtnf_reg_rule_flags_parse(u32 qflags
)
245 if (qflags
& QLINK_RRF_NO_OFDM
)
246 flags
|= NL80211_RRF_NO_OFDM
;
248 if (qflags
& QLINK_RRF_NO_CCK
)
249 flags
|= NL80211_RRF_NO_CCK
;
251 if (qflags
& QLINK_RRF_NO_INDOOR
)
252 flags
|= NL80211_RRF_NO_INDOOR
;
254 if (qflags
& QLINK_RRF_NO_OUTDOOR
)
255 flags
|= NL80211_RRF_NO_OUTDOOR
;
257 if (qflags
& QLINK_RRF_DFS
)
258 flags
|= NL80211_RRF_DFS
;
260 if (qflags
& QLINK_RRF_PTP_ONLY
)
261 flags
|= NL80211_RRF_PTP_ONLY
;
263 if (qflags
& QLINK_RRF_PTMP_ONLY
)
264 flags
|= NL80211_RRF_PTMP_ONLY
;
266 if (qflags
& QLINK_RRF_NO_IR
)
267 flags
|= NL80211_RRF_NO_IR
;
269 if (qflags
& QLINK_RRF_AUTO_BW
)
270 flags
|= NL80211_RRF_AUTO_BW
;
272 if (qflags
& QLINK_RRF_IR_CONCURRENT
)
273 flags
|= NL80211_RRF_IR_CONCURRENT
;
275 if (qflags
& QLINK_RRF_NO_HT40MINUS
)
276 flags
|= NL80211_RRF_NO_HT40MINUS
;
278 if (qflags
& QLINK_RRF_NO_HT40PLUS
)
279 flags
|= NL80211_RRF_NO_HT40PLUS
;
281 if (qflags
& QLINK_RRF_NO_80MHZ
)
282 flags
|= NL80211_RRF_NO_80MHZ
;
284 if (qflags
& QLINK_RRF_NO_160MHZ
)
285 flags
|= NL80211_RRF_NO_160MHZ
;
290 void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule
*rule
,
291 const struct qlink_tlv_reg_rule
*tlv
)
293 rule
->freq_range
.start_freq_khz
= le32_to_cpu(tlv
->start_freq_khz
);
294 rule
->freq_range
.end_freq_khz
= le32_to_cpu(tlv
->end_freq_khz
);
295 rule
->freq_range
.max_bandwidth_khz
=
296 le32_to_cpu(tlv
->max_bandwidth_khz
);
297 rule
->power_rule
.max_antenna_gain
= le32_to_cpu(tlv
->max_antenna_gain
);
298 rule
->power_rule
.max_eirp
= le32_to_cpu(tlv
->max_eirp
);
299 rule
->dfs_cac_ms
= le32_to_cpu(tlv
->dfs_cac_ms
);
300 rule
->flags
= qtnf_reg_rule_flags_parse(le32_to_cpu(tlv
->flags
));