1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation 4 * Copyright (C) 2015 Intel Mobile Communications GmbH 5 */ 6 #include <linux/types.h> 7 #include <linux/slab.h> 8 #include <linux/export.h> 9 #include "iwl-drv.h" 10 #include "iwl-modparams.h" 11 #include "iwl-nvm-utils.h" 12 13 int iwl_init_sband_channels(struct iwl_nvm_data *data, 14 struct ieee80211_supported_band *sband, 15 int n_channels, enum nl80211_band band) 16 { 17 struct ieee80211_channel *chan = &data->channels[0]; 18 int n = 0, idx = 0; 19 20 while (idx < n_channels && chan->band != band) 21 chan = &data->channels[++idx]; 22 23 sband->channels = &data->channels[idx]; 24 25 while (idx < n_channels && chan->band == band) { 26 chan = &data->channels[++idx]; 27 n++; 28 } 29 30 sband->n_channels = n; 31 32 return n; 33 } 34 IWL_EXPORT_SYMBOL(iwl_init_sband_channels); 35 36 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ 37 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ 38 39 void iwl_init_ht_hw_capab(struct iwl_trans *trans, 40 struct iwl_nvm_data *data, 41 struct ieee80211_sta_ht_cap *ht_info, 42 enum nl80211_band band, 43 u8 tx_chains, u8 rx_chains) 44 { 45 const struct iwl_cfg *cfg = trans->cfg; 46 int max_bit_rate = 0; 47 48 tx_chains = hweight8(tx_chains); 49 if (cfg->rx_with_siso_diversity) 50 rx_chains = 1; 51 else 52 rx_chains = hweight8(rx_chains); 53 54 if (!(data->sku_cap_11n_enable) || 55 (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) || 56 !cfg->ht_params) { 57 ht_info->ht_supported = false; 58 return; 59 } 60 61 if (data->sku_cap_mimo_disabled) 62 rx_chains = 1; 63 64 ht_info->ht_supported = true; 65 ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; 66 67 if (cfg->ht_params->stbc) { 68 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 69 70 if (tx_chains > 1) 71 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; 72 } 73 74 if (cfg->ht_params->ldpc) 75 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; 76 77 if (trans->trans_cfg->mq_rx_supported || 78 iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K) 79 ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; 80 81 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 82 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; 83 84 ht_info->mcs.rx_mask[0] = 0xFF; 85 ht_info->mcs.rx_mask[1] = 0x00; 86 ht_info->mcs.rx_mask[2] = 0x00; 87 88 if (rx_chains >= 2) 89 ht_info->mcs.rx_mask[1] = 0xFF; 90 if (rx_chains >= 3) 91 ht_info->mcs.rx_mask[2] = 0xFF; 92 93 if (cfg->ht_params->ht_greenfield_support) 94 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; 95 ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 96 97 max_bit_rate = MAX_BIT_RATE_20_MHZ; 98 99 if (cfg->ht_params->ht40_bands & BIT(band)) { 100 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; 101 ht_info->cap |= IEEE80211_HT_CAP_SGI_40; 102 max_bit_rate = MAX_BIT_RATE_40_MHZ; 103 } 104 105 /* Highest supported Rx data rate */ 106 max_bit_rate *= rx_chains; 107 WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); 108 ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); 109 110 /* Tx MCS capabilities */ 111 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 112 if (tx_chains != rx_chains) { 113 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 114 ht_info->mcs.tx_params |= ((tx_chains - 1) << 115 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 116 } 117 } 118 IWL_EXPORT_SYMBOL(iwl_init_ht_hw_capab); 119