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