1ff233cb5SSergey Matyukevich // SPDX-License-Identifier: GPL-2.0+ 2ff233cb5SSergey Matyukevich /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ 398f44cb0SIgor Mitsyanko 498f44cb0SIgor Mitsyanko #include <linux/nl80211.h> 598f44cb0SIgor Mitsyanko 698f44cb0SIgor Mitsyanko #include "qlink_util.h" 798f44cb0SIgor Mitsyanko 841c8fa0cSSergey Matyukevich u16 qlink_iface_type_to_nl_mask(u16 qlink_type) 998f44cb0SIgor Mitsyanko { 1098f44cb0SIgor Mitsyanko u16 result = 0; 1198f44cb0SIgor Mitsyanko 1241c8fa0cSSergey Matyukevich switch (qlink_type) { 1341c8fa0cSSergey Matyukevich case QLINK_IFTYPE_AP: 1498f44cb0SIgor Mitsyanko result |= BIT(NL80211_IFTYPE_AP); 1541c8fa0cSSergey Matyukevich break; 1641c8fa0cSSergey Matyukevich case QLINK_IFTYPE_STATION: 1798f44cb0SIgor Mitsyanko result |= BIT(NL80211_IFTYPE_STATION); 1841c8fa0cSSergey Matyukevich break; 1941c8fa0cSSergey Matyukevich case QLINK_IFTYPE_ADHOC: 2098f44cb0SIgor Mitsyanko result |= BIT(NL80211_IFTYPE_ADHOC); 2141c8fa0cSSergey Matyukevich break; 2241c8fa0cSSergey Matyukevich case QLINK_IFTYPE_MONITOR: 2398f44cb0SIgor Mitsyanko result |= BIT(NL80211_IFTYPE_MONITOR); 2441c8fa0cSSergey Matyukevich break; 2541c8fa0cSSergey Matyukevich case QLINK_IFTYPE_WDS: 2698f44cb0SIgor Mitsyanko result |= BIT(NL80211_IFTYPE_WDS); 2741c8fa0cSSergey Matyukevich break; 28805b28c0SSergey Matyukevich case QLINK_IFTYPE_AP_VLAN: 29805b28c0SSergey Matyukevich result |= BIT(NL80211_IFTYPE_AP_VLAN); 30805b28c0SSergey Matyukevich break; 3141c8fa0cSSergey Matyukevich } 3298f44cb0SIgor Mitsyanko 3398f44cb0SIgor Mitsyanko return result; 3498f44cb0SIgor Mitsyanko } 3598f44cb0SIgor Mitsyanko 3698f44cb0SIgor Mitsyanko u8 qlink_chan_width_mask_to_nl(u16 qlink_mask) 3798f44cb0SIgor Mitsyanko { 3898f44cb0SIgor Mitsyanko u8 result = 0; 3998f44cb0SIgor Mitsyanko 4077d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5)) 4198f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_5); 4298f44cb0SIgor Mitsyanko 4377d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10)) 4498f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_10); 4598f44cb0SIgor Mitsyanko 4677d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT)) 4798f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_20_NOHT); 4898f44cb0SIgor Mitsyanko 4977d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20)) 5098f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_20); 5198f44cb0SIgor Mitsyanko 5277d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40)) 5398f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_40); 5498f44cb0SIgor Mitsyanko 5577d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80)) 5698f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_80); 5798f44cb0SIgor Mitsyanko 5877d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80)) 5998f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_80P80); 6098f44cb0SIgor Mitsyanko 6177d68147SIgor Mitsyanko if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160)) 6298f44cb0SIgor Mitsyanko result |= BIT(NL80211_CHAN_WIDTH_160); 6398f44cb0SIgor Mitsyanko 6498f44cb0SIgor Mitsyanko return result; 6598f44cb0SIgor Mitsyanko } 66fac7f9bfSIgor Mitsyanko 67fac7f9bfSIgor Mitsyanko static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw) 68fac7f9bfSIgor Mitsyanko { 69fac7f9bfSIgor Mitsyanko switch (qlw) { 70fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_20_NOHT: 71fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_20_NOHT; 72fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_20: 73fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_20; 74fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_40: 75fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_40; 76fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_80: 77fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_80; 78fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_80P80: 79fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_80P80; 80fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_160: 81fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_160; 82fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_5: 83fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_5; 84fac7f9bfSIgor Mitsyanko case QLINK_CHAN_WIDTH_10: 85fac7f9bfSIgor Mitsyanko return NL80211_CHAN_WIDTH_10; 86fac7f9bfSIgor Mitsyanko default: 87fac7f9bfSIgor Mitsyanko return -1; 88fac7f9bfSIgor Mitsyanko } 89fac7f9bfSIgor Mitsyanko } 90fac7f9bfSIgor Mitsyanko 91f99201cbSIgor Mitsyanko static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth) 92f99201cbSIgor Mitsyanko { 93f99201cbSIgor Mitsyanko switch (nlwidth) { 94f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_20_NOHT: 95f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_20_NOHT; 96f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_20: 97f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_20; 98f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_40: 99f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_40; 100f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_80: 101f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_80; 102f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_80P80: 103f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_80P80; 104f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_160: 105f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_160; 106f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_5: 107f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_5; 108f99201cbSIgor Mitsyanko case NL80211_CHAN_WIDTH_10: 109f99201cbSIgor Mitsyanko return QLINK_CHAN_WIDTH_10; 110f99201cbSIgor Mitsyanko default: 111f99201cbSIgor Mitsyanko return -1; 112f99201cbSIgor Mitsyanko } 113f99201cbSIgor Mitsyanko } 114f99201cbSIgor Mitsyanko 1155bf374abSSergey Matyukevich void qlink_chandef_q2cfg(struct wiphy *wiphy, 1165bf374abSSergey Matyukevich const struct qlink_chandef *qch, 1175bf374abSSergey Matyukevich struct cfg80211_chan_def *chdef) 1185bf374abSSergey Matyukevich { 1195bf374abSSergey Matyukevich struct ieee80211_channel *chan; 1205bf374abSSergey Matyukevich 1215bf374abSSergey Matyukevich chan = ieee80211_get_channel(wiphy, le16_to_cpu(qch->chan.center_freq)); 1225bf374abSSergey Matyukevich 1235bf374abSSergey Matyukevich chdef->chan = chan; 1245bf374abSSergey Matyukevich chdef->center_freq1 = le16_to_cpu(qch->center_freq1); 1255bf374abSSergey Matyukevich chdef->center_freq2 = le16_to_cpu(qch->center_freq2); 1265bf374abSSergey Matyukevich chdef->width = qlink_chanwidth_to_nl(qch->width); 1275bf374abSSergey Matyukevich } 1285bf374abSSergey Matyukevich 129f99201cbSIgor Mitsyanko void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef, 130f99201cbSIgor Mitsyanko struct qlink_chandef *qch) 131f99201cbSIgor Mitsyanko { 1325bf374abSSergey Matyukevich struct ieee80211_channel *chan = chdef->chan; 1335bf374abSSergey Matyukevich 1345bf374abSSergey Matyukevich qch->chan.hw_value = cpu_to_le16(chan->hw_value); 1355bf374abSSergey Matyukevich qch->chan.center_freq = cpu_to_le16(chan->center_freq); 1365bf374abSSergey Matyukevich qch->chan.flags = cpu_to_le32(chan->flags); 1375bf374abSSergey Matyukevich 138f99201cbSIgor Mitsyanko qch->center_freq1 = cpu_to_le16(chdef->center_freq1); 139f99201cbSIgor Mitsyanko qch->center_freq2 = cpu_to_le16(chdef->center_freq2); 140f99201cbSIgor Mitsyanko qch->width = qlink_chanwidth_nl_to_qlink(chdef->width); 141f99201cbSIgor Mitsyanko } 142f99201cbSIgor Mitsyanko 1438b5f4aa7SIgor Mitsyanko enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val) 1448b5f4aa7SIgor Mitsyanko { 1458b5f4aa7SIgor Mitsyanko switch (nl_val) { 1468b5f4aa7SIgor Mitsyanko case NL80211_HIDDEN_SSID_ZERO_LEN: 1478b5f4aa7SIgor Mitsyanko return QLINK_HIDDEN_SSID_ZERO_LEN; 1488b5f4aa7SIgor Mitsyanko case NL80211_HIDDEN_SSID_ZERO_CONTENTS: 1498b5f4aa7SIgor Mitsyanko return QLINK_HIDDEN_SSID_ZERO_CONTENTS; 1508b5f4aa7SIgor Mitsyanko case NL80211_HIDDEN_SSID_NOT_IN_USE: 1518b5f4aa7SIgor Mitsyanko default: 1528b5f4aa7SIgor Mitsyanko return QLINK_HIDDEN_SSID_NOT_IN_USE; 1538b5f4aa7SIgor Mitsyanko } 1548b5f4aa7SIgor Mitsyanko } 1554d2a7a1cSIgor Mitsyanko 1564d2a7a1cSIgor Mitsyanko bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit, 1574d2a7a1cSIgor Mitsyanko unsigned int arr_max_len) 1584d2a7a1cSIgor Mitsyanko { 1594d2a7a1cSIgor Mitsyanko unsigned int idx = bit / BITS_PER_BYTE; 1604d2a7a1cSIgor Mitsyanko u8 mask = 1 << (bit - (idx * BITS_PER_BYTE)); 1614d2a7a1cSIgor Mitsyanko 1624d2a7a1cSIgor Mitsyanko if (idx >= arr_max_len) 1634d2a7a1cSIgor Mitsyanko return false; 1644d2a7a1cSIgor Mitsyanko 1654d2a7a1cSIgor Mitsyanko return arr[idx] & mask; 1664d2a7a1cSIgor Mitsyanko } 167f1398fd2SVasily Ulyanov 168f1398fd2SVasily Ulyanov void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl, 169f1398fd2SVasily Ulyanov struct qlink_acl_data *qacl) 170f1398fd2SVasily Ulyanov { 171f1398fd2SVasily Ulyanov switch (acl->acl_policy) { 172f1398fd2SVasily Ulyanov case NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: 173f1398fd2SVasily Ulyanov qacl->policy = 174f1398fd2SVasily Ulyanov cpu_to_le32(QLINK_ACL_POLICY_ACCEPT_UNLESS_LISTED); 175f1398fd2SVasily Ulyanov break; 176f1398fd2SVasily Ulyanov case NL80211_ACL_POLICY_DENY_UNLESS_LISTED: 177f1398fd2SVasily Ulyanov qacl->policy = cpu_to_le32(QLINK_ACL_POLICY_DENY_UNLESS_LISTED); 178f1398fd2SVasily Ulyanov break; 179f1398fd2SVasily Ulyanov } 180f1398fd2SVasily Ulyanov 181f1398fd2SVasily Ulyanov qacl->num_entries = cpu_to_le32(acl->n_acl_entries); 182f1398fd2SVasily Ulyanov memcpy(qacl->mac_addrs, acl->mac_addrs, 183f1398fd2SVasily Ulyanov acl->n_acl_entries * sizeof(*qacl->mac_addrs)); 184f1398fd2SVasily Ulyanov } 1852c31129fSIgor Mitsyanko 1862c31129fSIgor Mitsyanko enum qlink_band qlink_utils_band_cfg2q(enum nl80211_band band) 1872c31129fSIgor Mitsyanko { 1882c31129fSIgor Mitsyanko switch (band) { 1892c31129fSIgor Mitsyanko case NL80211_BAND_2GHZ: 1902c31129fSIgor Mitsyanko return QLINK_BAND_2GHZ; 1912c31129fSIgor Mitsyanko case NL80211_BAND_5GHZ: 1922c31129fSIgor Mitsyanko return QLINK_BAND_5GHZ; 1932c31129fSIgor Mitsyanko case NL80211_BAND_60GHZ: 1942c31129fSIgor Mitsyanko return QLINK_BAND_60GHZ; 1952c31129fSIgor Mitsyanko default: 1962c31129fSIgor Mitsyanko return -EINVAL; 1972c31129fSIgor Mitsyanko } 1982c31129fSIgor Mitsyanko } 1992c31129fSIgor Mitsyanko 2002c31129fSIgor Mitsyanko enum qlink_dfs_state qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state) 2012c31129fSIgor Mitsyanko { 2022c31129fSIgor Mitsyanko switch (state) { 2032c31129fSIgor Mitsyanko case NL80211_DFS_USABLE: 2042c31129fSIgor Mitsyanko return QLINK_DFS_USABLE; 2052c31129fSIgor Mitsyanko case NL80211_DFS_AVAILABLE: 2062c31129fSIgor Mitsyanko return QLINK_DFS_AVAILABLE; 2072c31129fSIgor Mitsyanko case NL80211_DFS_UNAVAILABLE: 2082c31129fSIgor Mitsyanko default: 2092c31129fSIgor Mitsyanko return QLINK_DFS_UNAVAILABLE; 2102c31129fSIgor Mitsyanko } 2112c31129fSIgor Mitsyanko } 2122c31129fSIgor Mitsyanko 2132c31129fSIgor Mitsyanko u32 qlink_utils_chflags_cfg2q(u32 cfgflags) 2142c31129fSIgor Mitsyanko { 2152c31129fSIgor Mitsyanko u32 flags = 0; 2162c31129fSIgor Mitsyanko 2172c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_DISABLED) 2182c31129fSIgor Mitsyanko flags |= QLINK_CHAN_DISABLED; 2192c31129fSIgor Mitsyanko 2202c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_NO_IR) 2212c31129fSIgor Mitsyanko flags |= QLINK_CHAN_NO_IR; 2222c31129fSIgor Mitsyanko 2232c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_RADAR) 2242c31129fSIgor Mitsyanko flags |= QLINK_CHAN_RADAR; 2252c31129fSIgor Mitsyanko 2262c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_NO_HT40PLUS) 2272c31129fSIgor Mitsyanko flags |= QLINK_CHAN_NO_HT40PLUS; 2282c31129fSIgor Mitsyanko 2292c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_NO_HT40MINUS) 2302c31129fSIgor Mitsyanko flags |= QLINK_CHAN_NO_HT40MINUS; 2312c31129fSIgor Mitsyanko 2322c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_NO_80MHZ) 2332c31129fSIgor Mitsyanko flags |= QLINK_CHAN_NO_80MHZ; 2342c31129fSIgor Mitsyanko 2352c31129fSIgor Mitsyanko if (cfgflags & IEEE80211_CHAN_NO_160MHZ) 2362c31129fSIgor Mitsyanko flags |= QLINK_CHAN_NO_160MHZ; 2372c31129fSIgor Mitsyanko 2382c31129fSIgor Mitsyanko return flags; 2392c31129fSIgor Mitsyanko } 240