1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2005-2014, 2018-2021, 2023, 2025 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_rf_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 /* there are no devices with HT but without HT40 entirely */ 57 !cfg->ht_params.ht40_bands) { 58 ht_info->ht_supported = false; 59 return; 60 } 61 62 if (data->sku_cap_mimo_disabled) 63 rx_chains = 1; 64 65 ht_info->ht_supported = true; 66 ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; 67 68 if (cfg->ht_params.stbc) { 69 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 70 71 if (tx_chains > 1) 72 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; 73 } 74 75 if (cfg->ht_params.ldpc) 76 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; 77 78 if (trans->mac_cfg->mq_rx_supported || 79 iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K) 80 ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; 81 82 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 83 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; 84 85 ht_info->mcs.rx_mask[0] = 0xFF; 86 ht_info->mcs.rx_mask[1] = 0x00; 87 ht_info->mcs.rx_mask[2] = 0x00; 88 89 if (rx_chains >= 2) 90 ht_info->mcs.rx_mask[1] = 0xFF; 91 if (rx_chains >= 3) 92 ht_info->mcs.rx_mask[2] = 0xFF; 93 94 if (cfg->ht_params.ht_greenfield_support) 95 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; 96 ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 97 98 max_bit_rate = MAX_BIT_RATE_20_MHZ; 99 100 if (cfg->ht_params.ht40_bands & BIT(band)) { 101 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; 102 ht_info->cap |= IEEE80211_HT_CAP_SGI_40; 103 max_bit_rate = MAX_BIT_RATE_40_MHZ; 104 } 105 106 /* Highest supported Rx data rate */ 107 max_bit_rate *= rx_chains; 108 WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); 109 ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); 110 111 /* Tx MCS capabilities */ 112 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 113 if (tx_chains != rx_chains) { 114 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 115 ht_info->mcs.tx_params |= ((tx_chains - 1) << 116 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 117 } 118 } 119 IWL_EXPORT_SYMBOL(iwl_init_ht_hw_capab); 120