1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> 4 */ 5 #include "mt76.h" 6 7 static struct mt76_vif_link * 8 mt76_alloc_mlink(struct mt76_dev *dev, struct mt76_vif_data *mvif) 9 { 10 struct mt76_vif_link *mlink; 11 12 mlink = kzalloc(dev->drv->link_data_size, GFP_KERNEL); 13 if (!mlink) 14 return NULL; 15 16 mlink->mvif = mvif; 17 18 return mlink; 19 } 20 21 static int 22 mt76_phy_update_channel(struct mt76_phy *phy, 23 struct ieee80211_chanctx_conf *conf) 24 { 25 phy->radar_enabled = conf->radar_enabled; 26 phy->main_chandef = conf->def; 27 phy->chanctx = (struct mt76_chanctx *)conf->drv_priv; 28 29 return __mt76_set_channel(phy, &phy->main_chandef, false); 30 } 31 32 int mt76_add_chanctx(struct ieee80211_hw *hw, 33 struct ieee80211_chanctx_conf *conf) 34 { 35 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 36 struct mt76_phy *phy = hw->priv; 37 struct mt76_dev *dev = phy->dev; 38 int ret = -EINVAL; 39 40 phy = ctx->phy = dev->band_phys[conf->def.chan->band]; 41 if (WARN_ON_ONCE(!phy)) 42 return ret; 43 44 if (dev->scan.phy == phy) 45 mt76_abort_scan(dev); 46 47 mutex_lock(&dev->mutex); 48 if (!phy->chanctx) 49 ret = mt76_phy_update_channel(phy, conf); 50 else 51 ret = 0; 52 mutex_unlock(&dev->mutex); 53 54 return ret; 55 } 56 EXPORT_SYMBOL_GPL(mt76_add_chanctx); 57 58 void mt76_remove_chanctx(struct ieee80211_hw *hw, 59 struct ieee80211_chanctx_conf *conf) 60 { 61 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 62 struct mt76_phy *phy = hw->priv; 63 struct mt76_dev *dev = phy->dev; 64 65 phy = ctx->phy; 66 if (WARN_ON_ONCE(!phy)) 67 return; 68 69 if (dev->scan.phy == phy) 70 mt76_abort_scan(dev); 71 72 mutex_lock(&dev->mutex); 73 if (phy->chanctx == ctx) 74 phy->chanctx = NULL; 75 mutex_unlock(&dev->mutex); 76 } 77 EXPORT_SYMBOL_GPL(mt76_remove_chanctx); 78 79 void mt76_change_chanctx(struct ieee80211_hw *hw, 80 struct ieee80211_chanctx_conf *conf, 81 u32 changed) 82 { 83 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 84 struct mt76_phy *phy = ctx->phy; 85 struct mt76_dev *dev = phy->dev; 86 87 if (!(changed & (IEEE80211_CHANCTX_CHANGE_WIDTH | 88 IEEE80211_CHANCTX_CHANGE_RADAR))) 89 return; 90 91 if (phy->roc_vif) 92 mt76_abort_roc(phy); 93 94 cancel_delayed_work_sync(&phy->mac_work); 95 96 mutex_lock(&dev->mutex); 97 mt76_phy_update_channel(phy, conf); 98 mutex_unlock(&dev->mutex); 99 } 100 EXPORT_SYMBOL_GPL(mt76_change_chanctx); 101 102 103 int mt76_assign_vif_chanctx(struct ieee80211_hw *hw, 104 struct ieee80211_vif *vif, 105 struct ieee80211_bss_conf *link_conf, 106 struct ieee80211_chanctx_conf *conf) 107 { 108 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 109 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 110 struct mt76_vif_data *mvif = mlink->mvif; 111 int link_id = link_conf->link_id; 112 struct mt76_phy *phy = ctx->phy; 113 struct mt76_dev *dev = phy->dev; 114 bool mlink_alloc = false; 115 int ret = 0; 116 117 if (dev->scan.vif == vif) 118 mt76_abort_scan(dev); 119 120 mutex_lock(&dev->mutex); 121 122 if (vif->type == NL80211_IFTYPE_MONITOR && 123 is_zero_ether_addr(vif->addr)) 124 goto out; 125 126 mlink = mt76_vif_conf_link(dev, vif, link_conf); 127 if (!mlink) { 128 mlink = mt76_alloc_mlink(dev, mvif); 129 if (!mlink) { 130 ret = -ENOMEM; 131 goto out; 132 } 133 mlink_alloc = true; 134 } 135 136 mlink->ctx = conf; 137 ret = dev->drv->vif_link_add(phy, vif, link_conf, mlink); 138 if (ret) { 139 if (mlink_alloc) 140 kfree(mlink); 141 goto out; 142 } 143 144 if (link_conf != &vif->bss_conf) 145 rcu_assign_pointer(mvif->link[link_id], mlink); 146 147 out: 148 mutex_unlock(&dev->mutex); 149 150 return ret; 151 } 152 EXPORT_SYMBOL_GPL(mt76_assign_vif_chanctx); 153 154 void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, 155 struct ieee80211_vif *vif, 156 struct ieee80211_bss_conf *link_conf, 157 struct ieee80211_chanctx_conf *conf) 158 { 159 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 160 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 161 struct mt76_phy *phy = ctx->phy; 162 struct mt76_dev *dev = phy->dev; 163 164 if (dev->scan.vif == vif) 165 mt76_abort_scan(dev); 166 167 mutex_lock(&dev->mutex); 168 169 if (vif->type == NL80211_IFTYPE_MONITOR && 170 is_zero_ether_addr(vif->addr)) 171 goto out; 172 173 mlink = mt76_vif_conf_link(dev, vif, link_conf); 174 if (!mlink) 175 goto out; 176 177 dev->drv->vif_link_remove(phy, vif, link_conf, mlink); 178 mlink->ctx = NULL; 179 out: 180 mutex_unlock(&dev->mutex); 181 } 182 EXPORT_SYMBOL_GPL(mt76_unassign_vif_chanctx); 183 184 int mt76_switch_vif_chanctx(struct ieee80211_hw *hw, 185 struct ieee80211_vif_chanctx_switch *vifs, 186 int n_vifs, 187 enum ieee80211_chanctx_switch_mode mode) 188 { 189 struct ieee80211_vif_chanctx_switch *v; 190 struct mt76_chanctx *old_ctx, *new_ctx; 191 struct mt76_phy *old_phy, *phy = hw->priv; 192 struct mt76_dev *dev = phy->dev; 193 struct mt76_vif_link *mlink; 194 bool need_update[__MT_MAX_BAND] = {}; 195 int i, ret = 0; 196 197 for (i = 0; i < n_vifs; i++) { 198 v = &vifs[i]; 199 new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv; 200 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) 201 phy = new_ctx->phy = dev->band_phys[v->new_ctx->def.chan->band]; 202 else 203 phy = new_ctx->phy; 204 205 if (!phy) 206 return -EINVAL; 207 208 if (need_update[phy->band_idx]) 209 continue; 210 211 if (phy->chanctx != new_ctx) { 212 if (dev->scan.phy == phy) 213 mt76_abort_scan(dev); 214 215 cancel_delayed_work_sync(&phy->mac_work); 216 need_update[phy->band_idx] = true; 217 } 218 } 219 220 mutex_lock(&dev->mutex); 221 222 for (i = 0; i < n_vifs; i++) { 223 v = &vifs[i]; 224 old_ctx = (struct mt76_chanctx *)v->old_ctx->drv_priv; 225 old_phy = old_ctx->phy; 226 227 new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv; 228 phy = new_ctx->phy; 229 230 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && old_phy->chanctx && 231 old_phy->chanctx == old_ctx && phy != old_phy) 232 old_phy->chanctx = NULL; 233 234 if (need_update[phy->band_idx]) { 235 ret = mt76_phy_update_channel(phy, v->new_ctx); 236 if (ret) 237 goto out; 238 239 need_update[phy->band_idx] = false; 240 } 241 242 mlink = mt76_vif_conf_link(dev, v->vif, v->link_conf); 243 if (!mlink) 244 continue; 245 246 if (old_phy != phy) { 247 dev->drv->vif_link_remove(old_phy, v->vif, v->link_conf, 248 mlink); 249 250 ret = dev->drv->vif_link_add(phy, v->vif, v->link_conf, 251 mlink); 252 if (ret) 253 goto out; 254 } 255 256 mlink->ctx = v->new_ctx; 257 if (mlink->beacon_mon_interval) 258 WRITE_ONCE(mlink->beacon_mon_last, jiffies); 259 } 260 261 out: 262 mutex_unlock(&dev->mutex); 263 264 return ret; 265 } 266 EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx); 267 268 struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, 269 struct ieee80211_vif *vif) 270 { 271 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 272 struct mt76_vif_data *mvif = mlink->mvif; 273 struct mt76_dev *dev = phy->dev; 274 int i, ret; 275 276 for (i = 0; i < ARRAY_SIZE(mvif->link); i++) { 277 mlink = mt76_dereference(mvif->link[i], dev); 278 if (!mlink) 279 continue; 280 281 if (mt76_vif_link_phy(mlink) == phy) 282 return mlink; 283 } 284 285 if (!dev->drv->vif_link_add) 286 return ERR_PTR(-EINVAL); 287 288 mlink = mt76_alloc_mlink(dev, mvif); 289 if (!mlink) 290 return ERR_PTR(-ENOMEM); 291 292 mlink->offchannel = true; 293 ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink); 294 if (ret) { 295 kfree(mlink); 296 return ERR_PTR(ret); 297 } 298 rcu_assign_pointer(mvif->offchannel_link, mlink); 299 300 return mlink; 301 } 302 303 void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, 304 struct mt76_vif_link *mlink) 305 { 306 struct mt76_dev *dev = phy->dev; 307 struct mt76_vif_data *mvif; 308 309 if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel) 310 return; 311 312 mvif = mlink->mvif; 313 314 rcu_assign_pointer(mvif->offchannel_link, NULL); 315 dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink); 316 kfree_rcu(mlink, rcu_head); 317 } 318 319 void mt76_roc_complete(struct mt76_phy *phy) 320 { 321 struct mt76_vif_link *mlink = phy->roc_link; 322 struct mt76_dev *dev = phy->dev; 323 324 if (!phy->roc_vif) 325 return; 326 327 if (mlink) 328 mlink->mvif->roc_phy = NULL; 329 if (phy->chanctx && phy->main_chandef.chan && phy->offchannel && 330 !test_bit(MT76_MCU_RESET, &dev->phy.state)) { 331 __mt76_set_channel(phy, &phy->main_chandef, false); 332 mt76_offchannel_notify(phy, false); 333 } 334 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link); 335 phy->roc_vif = NULL; 336 phy->roc_link = NULL; 337 if (!test_bit(MT76_MCU_RESET, &dev->phy.state)) 338 ieee80211_remain_on_channel_expired(phy->hw); 339 } 340 341 void mt76_roc_complete_work(struct work_struct *work) 342 { 343 struct mt76_phy *phy = container_of(work, struct mt76_phy, roc_work.work); 344 struct mt76_dev *dev = phy->dev; 345 346 mutex_lock(&dev->mutex); 347 mt76_roc_complete(phy); 348 mutex_unlock(&dev->mutex); 349 } 350 351 void mt76_abort_roc(struct mt76_phy *phy) 352 { 353 struct mt76_dev *dev = phy->dev; 354 355 cancel_delayed_work_sync(&phy->roc_work); 356 357 mutex_lock(&dev->mutex); 358 mt76_roc_complete(phy); 359 mutex_unlock(&dev->mutex); 360 } 361 EXPORT_SYMBOL_GPL(mt76_abort_roc); 362 363 int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 364 struct ieee80211_channel *chan, int duration, 365 enum ieee80211_roc_type type) 366 { 367 struct cfg80211_chan_def chandef = {}; 368 struct mt76_phy *phy = hw->priv; 369 struct mt76_dev *dev = phy->dev; 370 struct mt76_vif_link *mlink; 371 bool offchannel; 372 int ret = 0; 373 374 phy = dev->band_phys[chan->band]; 375 if (!phy) 376 return -EINVAL; 377 378 cancel_delayed_work_sync(&phy->mac_work); 379 380 mutex_lock(&dev->mutex); 381 382 if (phy->roc_vif || dev->scan.phy == phy || 383 test_bit(MT76_MCU_RESET, &dev->phy.state)) { 384 ret = -EBUSY; 385 goto out; 386 } 387 388 mlink = mt76_get_vif_phy_link(phy, vif); 389 if (IS_ERR(mlink)) { 390 ret = PTR_ERR(mlink); 391 goto out; 392 } 393 394 mlink->mvif->roc_phy = phy; 395 phy->roc_vif = vif; 396 phy->roc_link = mlink; 397 398 offchannel = mt76_offchannel_chandef(phy, chan, &chandef); 399 if (offchannel) 400 mt76_offchannel_notify(phy, true); 401 ret = __mt76_set_channel(phy, &chandef, offchannel); 402 if (ret) { 403 mlink->mvif->roc_phy = NULL; 404 phy->roc_vif = NULL; 405 phy->roc_link = NULL; 406 mt76_put_vif_phy_link(phy, vif, mlink); 407 goto out; 408 } 409 ieee80211_ready_on_channel(hw); 410 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work, 411 msecs_to_jiffies(duration)); 412 413 out: 414 mutex_unlock(&dev->mutex); 415 return ret; 416 } 417 EXPORT_SYMBOL_GPL(mt76_remain_on_channel); 418 419 int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, 420 struct ieee80211_vif *vif) 421 { 422 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 423 struct mt76_vif_data *mvif = mlink->mvif; 424 struct mt76_phy *phy = mvif->roc_phy; 425 426 if (!phy) 427 return 0; 428 429 mt76_abort_roc(phy); 430 431 return 0; 432 } 433 EXPORT_SYMBOL_GPL(mt76_cancel_remain_on_channel); 434