Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
0003 
0004 #include <linux/nl80211.h>
0005 
0006 #include "qlink_util.h"
0007 
0008 u16 qlink_iface_type_to_nl_mask(u16 qlink_type)
0009 {
0010     u16 result = 0;
0011 
0012     switch (qlink_type) {
0013     case QLINK_IFTYPE_AP:
0014         result |= BIT(NL80211_IFTYPE_AP);
0015         break;
0016     case QLINK_IFTYPE_STATION:
0017         result |= BIT(NL80211_IFTYPE_STATION);
0018         break;
0019     case QLINK_IFTYPE_ADHOC:
0020         result |= BIT(NL80211_IFTYPE_ADHOC);
0021         break;
0022     case QLINK_IFTYPE_MONITOR:
0023         result |= BIT(NL80211_IFTYPE_MONITOR);
0024         break;
0025     case QLINK_IFTYPE_WDS:
0026         result |= BIT(NL80211_IFTYPE_WDS);
0027         break;
0028     case QLINK_IFTYPE_AP_VLAN:
0029         result |= BIT(NL80211_IFTYPE_AP_VLAN);
0030         break;
0031     }
0032 
0033     return result;
0034 }
0035 
0036 u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)
0037 {
0038     u8 result = 0;
0039 
0040     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5))
0041         result |= BIT(NL80211_CHAN_WIDTH_5);
0042 
0043     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10))
0044         result |= BIT(NL80211_CHAN_WIDTH_10);
0045 
0046     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT))
0047         result |= BIT(NL80211_CHAN_WIDTH_20_NOHT);
0048 
0049     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20))
0050         result |= BIT(NL80211_CHAN_WIDTH_20);
0051 
0052     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40))
0053         result |= BIT(NL80211_CHAN_WIDTH_40);
0054 
0055     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80))
0056         result |= BIT(NL80211_CHAN_WIDTH_80);
0057 
0058     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80))
0059         result |= BIT(NL80211_CHAN_WIDTH_80P80);
0060 
0061     if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160))
0062         result |= BIT(NL80211_CHAN_WIDTH_160);
0063 
0064     return result;
0065 }
0066 
0067 static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw)
0068 {
0069     switch (qlw) {
0070     case QLINK_CHAN_WIDTH_20_NOHT:
0071         return NL80211_CHAN_WIDTH_20_NOHT;
0072     case QLINK_CHAN_WIDTH_20:
0073         return NL80211_CHAN_WIDTH_20;
0074     case QLINK_CHAN_WIDTH_40:
0075         return NL80211_CHAN_WIDTH_40;
0076     case QLINK_CHAN_WIDTH_80:
0077         return NL80211_CHAN_WIDTH_80;
0078     case QLINK_CHAN_WIDTH_80P80:
0079         return NL80211_CHAN_WIDTH_80P80;
0080     case QLINK_CHAN_WIDTH_160:
0081         return NL80211_CHAN_WIDTH_160;
0082     case QLINK_CHAN_WIDTH_5:
0083         return NL80211_CHAN_WIDTH_5;
0084     case QLINK_CHAN_WIDTH_10:
0085         return NL80211_CHAN_WIDTH_10;
0086     default:
0087         return -1;
0088     }
0089 }
0090 
0091 static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth)
0092 {
0093     switch (nlwidth) {
0094     case NL80211_CHAN_WIDTH_20_NOHT:
0095         return QLINK_CHAN_WIDTH_20_NOHT;
0096     case NL80211_CHAN_WIDTH_20:
0097         return QLINK_CHAN_WIDTH_20;
0098     case NL80211_CHAN_WIDTH_40:
0099         return QLINK_CHAN_WIDTH_40;
0100     case NL80211_CHAN_WIDTH_80:
0101         return QLINK_CHAN_WIDTH_80;
0102     case NL80211_CHAN_WIDTH_80P80:
0103         return QLINK_CHAN_WIDTH_80P80;
0104     case NL80211_CHAN_WIDTH_160:
0105         return QLINK_CHAN_WIDTH_160;
0106     case NL80211_CHAN_WIDTH_5:
0107         return QLINK_CHAN_WIDTH_5;
0108     case NL80211_CHAN_WIDTH_10:
0109         return QLINK_CHAN_WIDTH_10;
0110     default:
0111         return -1;
0112     }
0113 }
0114 
0115 void qlink_chandef_q2cfg(struct wiphy *wiphy,
0116              const struct qlink_chandef *qch,
0117              struct cfg80211_chan_def *chdef)
0118 {
0119     struct ieee80211_channel *chan;
0120 
0121     chan = ieee80211_get_channel(wiphy, le16_to_cpu(qch->chan.center_freq));
0122 
0123     chdef->chan = chan;
0124     chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
0125     chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
0126     chdef->width = qlink_chanwidth_to_nl(qch->width);
0127     chdef->edmg.bw_config = 0;
0128     chdef->edmg.channels = 0;
0129 }
0130 
0131 void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
0132              struct qlink_chandef *qch)
0133 {
0134     struct ieee80211_channel *chan = chdef->chan;
0135 
0136     qch->chan.hw_value = cpu_to_le16(chan->hw_value);
0137     qch->chan.center_freq = cpu_to_le16(chan->center_freq);
0138     qch->chan.flags = cpu_to_le32(chan->flags);
0139 
0140     qch->center_freq1 = cpu_to_le16(chdef->center_freq1);
0141     qch->center_freq2 = cpu_to_le16(chdef->center_freq2);
0142     qch->width = qlink_chanwidth_nl_to_qlink(chdef->width);
0143 }
0144 
0145 enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val)
0146 {
0147     switch (nl_val) {
0148     case NL80211_HIDDEN_SSID_ZERO_LEN:
0149         return QLINK_HIDDEN_SSID_ZERO_LEN;
0150     case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
0151         return QLINK_HIDDEN_SSID_ZERO_CONTENTS;
0152     case NL80211_HIDDEN_SSID_NOT_IN_USE:
0153     default:
0154         return QLINK_HIDDEN_SSID_NOT_IN_USE;
0155     }
0156 }
0157 
0158 bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit,
0159                unsigned int arr_max_len)
0160 {
0161     unsigned int idx = bit / BITS_PER_BYTE;
0162     u8 mask = 1 << (bit - (idx * BITS_PER_BYTE));
0163 
0164     if (idx >= arr_max_len)
0165         return false;
0166 
0167     return arr[idx] & mask;
0168 }
0169 
0170 void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl,
0171               struct qlink_acl_data *qacl)
0172 {
0173     switch (acl->acl_policy) {
0174     case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED:
0175         qacl->policy =
0176             cpu_to_le32(QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED);
0177         break;
0178     case NL80211_ACL_POLICY_DENY_UNLESS_LISTED:
0179         qacl->policy = cpu_to_le32(QLINK_ACL_POLICY_DENY_UNLESS_LISTED);
0180         break;
0181     }
0182 
0183     qacl->num_entries = cpu_to_le32(acl->n_acl_entries);
0184     memcpy(qacl->mac_addrs, acl->mac_addrs,
0185            acl->n_acl_entries * sizeof(*qacl->mac_addrs));
0186 }
0187 
0188 enum qlink_band qlink_utils_band_cfg2q(enum nl80211_band band)
0189 {
0190     switch (band) {
0191     case NL80211_BAND_2GHZ:
0192         return QLINK_BAND_2GHZ;
0193     case NL80211_BAND_5GHZ:
0194         return QLINK_BAND_5GHZ;
0195     case NL80211_BAND_60GHZ:
0196         return QLINK_BAND_60GHZ;
0197     default:
0198         return -EINVAL;
0199     }
0200 }
0201 
0202 enum qlink_dfs_state qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state)
0203 {
0204     switch (state) {
0205     case NL80211_DFS_USABLE:
0206         return QLINK_DFS_USABLE;
0207     case NL80211_DFS_AVAILABLE:
0208         return QLINK_DFS_AVAILABLE;
0209     case NL80211_DFS_UNAVAILABLE:
0210     default:
0211         return QLINK_DFS_UNAVAILABLE;
0212     }
0213 }
0214 
0215 u32 qlink_utils_chflags_cfg2q(u32 cfgflags)
0216 {
0217     u32 flags = 0;
0218 
0219     if (cfgflags & IEEE80211_CHAN_DISABLED)
0220         flags |= QLINK_CHAN_DISABLED;
0221 
0222     if (cfgflags & IEEE80211_CHAN_NO_IR)
0223         flags |= QLINK_CHAN_NO_IR;
0224 
0225     if (cfgflags & IEEE80211_CHAN_RADAR)
0226         flags |= QLINK_CHAN_RADAR;
0227 
0228     if (cfgflags & IEEE80211_CHAN_NO_HT40PLUS)
0229         flags |= QLINK_CHAN_NO_HT40PLUS;
0230 
0231     if (cfgflags & IEEE80211_CHAN_NO_HT40MINUS)
0232         flags |= QLINK_CHAN_NO_HT40MINUS;
0233 
0234     if (cfgflags & IEEE80211_CHAN_NO_80MHZ)
0235         flags |= QLINK_CHAN_NO_80MHZ;
0236 
0237     if (cfgflags & IEEE80211_CHAN_NO_160MHZ)
0238         flags |= QLINK_CHAN_NO_160MHZ;
0239 
0240     return flags;
0241 }
0242 
0243 static u32 qtnf_reg_rule_flags_parse(u32 qflags)
0244 {
0245     u32 flags = 0;
0246 
0247     if (qflags & QLINK_RRF_NO_OFDM)
0248         flags |= NL80211_RRF_NO_OFDM;
0249 
0250     if (qflags & QLINK_RRF_NO_CCK)
0251         flags |= NL80211_RRF_NO_CCK;
0252 
0253     if (qflags & QLINK_RRF_NO_INDOOR)
0254         flags |= NL80211_RRF_NO_INDOOR;
0255 
0256     if (qflags & QLINK_RRF_NO_OUTDOOR)
0257         flags |= NL80211_RRF_NO_OUTDOOR;
0258 
0259     if (qflags & QLINK_RRF_DFS)
0260         flags |= NL80211_RRF_DFS;
0261 
0262     if (qflags & QLINK_RRF_PTP_ONLY)
0263         flags |= NL80211_RRF_PTP_ONLY;
0264 
0265     if (qflags & QLINK_RRF_PTMP_ONLY)
0266         flags |= NL80211_RRF_PTMP_ONLY;
0267 
0268     if (qflags & QLINK_RRF_NO_IR)
0269         flags |= NL80211_RRF_NO_IR;
0270 
0271     if (qflags & QLINK_RRF_AUTO_BW)
0272         flags |= NL80211_RRF_AUTO_BW;
0273 
0274     if (qflags & QLINK_RRF_IR_CONCURRENT)
0275         flags |= NL80211_RRF_IR_CONCURRENT;
0276 
0277     if (qflags & QLINK_RRF_NO_HT40MINUS)
0278         flags |= NL80211_RRF_NO_HT40MINUS;
0279 
0280     if (qflags & QLINK_RRF_NO_HT40PLUS)
0281         flags |= NL80211_RRF_NO_HT40PLUS;
0282 
0283     if (qflags & QLINK_RRF_NO_80MHZ)
0284         flags |= NL80211_RRF_NO_80MHZ;
0285 
0286     if (qflags & QLINK_RRF_NO_160MHZ)
0287         flags |= NL80211_RRF_NO_160MHZ;
0288 
0289     return flags;
0290 }
0291 
0292 void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule *rule,
0293                   const struct qlink_tlv_reg_rule *tlv)
0294 {
0295     rule->freq_range.start_freq_khz = le32_to_cpu(tlv->start_freq_khz);
0296     rule->freq_range.end_freq_khz = le32_to_cpu(tlv->end_freq_khz);
0297     rule->freq_range.max_bandwidth_khz =
0298         le32_to_cpu(tlv->max_bandwidth_khz);
0299     rule->power_rule.max_antenna_gain = le32_to_cpu(tlv->max_antenna_gain);
0300     rule->power_rule.max_eirp = le32_to_cpu(tlv->max_eirp);
0301     rule->dfs_cac_ms = le32_to_cpu(tlv->dfs_cac_ms);
0302     rule->flags = qtnf_reg_rule_flags_parse(le32_to_cpu(tlv->flags));
0303 }