1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2020-2022 Realtek Corporation 3 */ 4 5 #include "chan.h" 6 #include "debug.h" 7 8 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band, 9 u8 center_chan) 10 { 11 switch (band) { 12 default: 13 case RTW89_BAND_2G: 14 switch (center_chan) { 15 default: 16 case 1 ... 14: 17 return RTW89_CH_2G; 18 } 19 case RTW89_BAND_5G: 20 switch (center_chan) { 21 default: 22 case 36 ... 64: 23 return RTW89_CH_5G_BAND_1; 24 case 100 ... 144: 25 return RTW89_CH_5G_BAND_3; 26 case 149 ... 177: 27 return RTW89_CH_5G_BAND_4; 28 } 29 case RTW89_BAND_6G: 30 switch (center_chan) { 31 default: 32 case 1 ... 29: 33 return RTW89_CH_6G_BAND_IDX0; 34 case 33 ... 61: 35 return RTW89_CH_6G_BAND_IDX1; 36 case 65 ... 93: 37 return RTW89_CH_6G_BAND_IDX2; 38 case 97 ... 125: 39 return RTW89_CH_6G_BAND_IDX3; 40 case 129 ... 157: 41 return RTW89_CH_6G_BAND_IDX4; 42 case 161 ... 189: 43 return RTW89_CH_6G_BAND_IDX5; 44 case 193 ... 221: 45 return RTW89_CH_6G_BAND_IDX6; 46 case 225 ... 253: 47 return RTW89_CH_6G_BAND_IDX7; 48 } 49 } 50 } 51 52 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw, 53 u32 center_freq, 54 u32 primary_freq) 55 { 56 u8 primary_chan_idx; 57 u32 offset; 58 59 switch (bw) { 60 default: 61 case RTW89_CHANNEL_WIDTH_20: 62 primary_chan_idx = RTW89_SC_DONT_CARE; 63 break; 64 case RTW89_CHANNEL_WIDTH_40: 65 if (primary_freq > center_freq) 66 primary_chan_idx = RTW89_SC_20_UPPER; 67 else 68 primary_chan_idx = RTW89_SC_20_LOWER; 69 break; 70 case RTW89_CHANNEL_WIDTH_80: 71 case RTW89_CHANNEL_WIDTH_160: 72 if (primary_freq > center_freq) { 73 offset = (primary_freq - center_freq - 10) / 20; 74 primary_chan_idx = RTW89_SC_20_UPPER + offset * 2; 75 } else { 76 offset = (center_freq - primary_freq - 10) / 20; 77 primary_chan_idx = RTW89_SC_20_LOWER + offset * 2; 78 } 79 break; 80 } 81 82 return primary_chan_idx; 83 } 84 85 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan, 86 enum rtw89_band band, enum rtw89_bandwidth bandwidth) 87 { 88 enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); 89 u32 center_freq, primary_freq; 90 91 memset(chan, 0, sizeof(*chan)); 92 chan->channel = center_chan; 93 chan->primary_channel = primary_chan; 94 chan->band_type = band; 95 chan->band_width = bandwidth; 96 97 center_freq = ieee80211_channel_to_frequency(center_chan, nl_band); 98 primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band); 99 100 chan->freq = center_freq; 101 chan->subband_type = rtw89_get_subband_type(band, center_chan); 102 chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq, 103 primary_freq); 104 } 105 106 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, 107 enum rtw89_sub_entity_idx idx, 108 const struct rtw89_chan *new) 109 { 110 struct rtw89_hal *hal = &rtwdev->hal; 111 struct rtw89_chan *chan = &hal->chan[idx]; 112 struct rtw89_chan_rcd *rcd = &hal->chan_rcd[idx]; 113 bool band_changed; 114 115 rcd->prev_primary_channel = chan->primary_channel; 116 rcd->prev_band_type = chan->band_type; 117 band_changed = new->band_type != chan->band_type; 118 119 *chan = *new; 120 return band_changed; 121 } 122 123 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, 124 enum rtw89_sub_entity_idx idx, 125 const struct cfg80211_chan_def *chandef, 126 bool from_stack) 127 { 128 struct rtw89_hal *hal = &rtwdev->hal; 129 130 hal->chandef[idx] = *chandef; 131 132 if (from_stack) 133 set_bit(idx, hal->entity_map); 134 } 135 136 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, 137 enum rtw89_sub_entity_idx idx, 138 const struct cfg80211_chan_def *chandef) 139 { 140 __rtw89_config_entity_chandef(rtwdev, idx, chandef, true); 141 } 142 143 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev) 144 { 145 struct cfg80211_chan_def chandef = {0}; 146 147 rtw89_get_default_chandef(&chandef); 148 __rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false); 149 } 150 151 void rtw89_entity_init(struct rtw89_dev *rtwdev) 152 { 153 struct rtw89_hal *hal = &rtwdev->hal; 154 155 bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); 156 rtw89_config_default_chandef(rtwdev); 157 } 158 159 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev) 160 { 161 struct rtw89_hal *hal = &rtwdev->hal; 162 enum rtw89_entity_mode mode; 163 u8 weight; 164 165 weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); 166 switch (weight) { 167 default: 168 rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight); 169 bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); 170 fallthrough; 171 case 0: 172 rtw89_config_default_chandef(rtwdev); 173 fallthrough; 174 case 1: 175 mode = RTW89_ENTITY_MODE_SCC; 176 break; 177 } 178 179 rtw89_set_entity_mode(rtwdev, mode); 180 return mode; 181 } 182 183 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, 184 struct ieee80211_chanctx_conf *ctx) 185 { 186 struct rtw89_hal *hal = &rtwdev->hal; 187 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 188 const struct rtw89_chip_info *chip = rtwdev->chip; 189 u8 idx; 190 191 idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); 192 if (idx >= chip->support_chanctx_num) 193 return -ENOENT; 194 195 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def); 196 rtw89_set_channel(rtwdev); 197 cfg->idx = idx; 198 return 0; 199 } 200 201 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, 202 struct ieee80211_chanctx_conf *ctx) 203 { 204 struct rtw89_hal *hal = &rtwdev->hal; 205 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 206 207 clear_bit(cfg->idx, hal->entity_map); 208 rtw89_set_channel(rtwdev); 209 } 210 211 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, 212 struct ieee80211_chanctx_conf *ctx, 213 u32 changed) 214 { 215 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 216 u8 idx = cfg->idx; 217 218 if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) { 219 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def); 220 rtw89_set_channel(rtwdev); 221 } 222 } 223 224 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, 225 struct rtw89_vif *rtwvif, 226 struct ieee80211_chanctx_conf *ctx) 227 { 228 return 0; 229 } 230 231 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, 232 struct rtw89_vif *rtwvif, 233 struct ieee80211_chanctx_conf *ctx) 234 { 235 } 236