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 mt76_chanctx *old_ctx = (struct mt76_chanctx *)vifs->old_ctx->drv_priv; 190 struct mt76_chanctx *new_ctx = (struct mt76_chanctx *)vifs->new_ctx->drv_priv; 191 struct ieee80211_chanctx_conf *conf = vifs->new_ctx; 192 struct mt76_phy *old_phy = old_ctx->phy; 193 struct mt76_phy *phy = hw->priv; 194 struct mt76_dev *dev = phy->dev; 195 struct mt76_vif_link *mlink; 196 bool update_chan; 197 int i, ret = 0; 198 199 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) 200 phy = new_ctx->phy = dev->band_phys[conf->def.chan->band]; 201 else 202 phy = new_ctx->phy; 203 if (!phy) 204 return -EINVAL; 205 206 update_chan = phy->chanctx != new_ctx; 207 if (update_chan) { 208 if (dev->scan.phy == phy) 209 mt76_abort_scan(dev); 210 211 cancel_delayed_work_sync(&phy->mac_work); 212 } 213 214 mutex_lock(&dev->mutex); 215 216 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && 217 phy != old_phy && old_phy->chanctx == old_ctx) 218 old_phy->chanctx = NULL; 219 220 if (update_chan) 221 ret = mt76_phy_update_channel(phy, vifs->new_ctx); 222 223 if (ret) 224 goto out; 225 226 if (old_phy == phy) 227 goto skip_link_replace; 228 229 for (i = 0; i < n_vifs; i++) { 230 mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); 231 if (!mlink) 232 continue; 233 234 dev->drv->vif_link_remove(old_phy, vifs[i].vif, 235 vifs[i].link_conf, mlink); 236 237 ret = dev->drv->vif_link_add(phy, vifs[i].vif, 238 vifs[i].link_conf, mlink); 239 if (ret) 240 goto out; 241 242 } 243 244 skip_link_replace: 245 for (i = 0; i < n_vifs; i++) { 246 mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); 247 if (!mlink) 248 continue; 249 250 mlink->ctx = vifs->new_ctx; 251 if (mlink->beacon_mon_interval) 252 WRITE_ONCE(mlink->beacon_mon_last, jiffies); 253 } 254 255 out: 256 mutex_unlock(&dev->mutex); 257 258 return ret; 259 } 260 EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx); 261 262 struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, 263 struct ieee80211_vif *vif) 264 { 265 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 266 struct mt76_vif_data *mvif = mlink->mvif; 267 struct mt76_dev *dev = phy->dev; 268 int i, ret; 269 270 for (i = 0; i < ARRAY_SIZE(mvif->link); i++) { 271 mlink = mt76_dereference(mvif->link[i], dev); 272 if (!mlink) 273 continue; 274 275 if (mt76_vif_link_phy(mlink) == phy) 276 return mlink; 277 } 278 279 if (!dev->drv->vif_link_add) 280 return ERR_PTR(-EINVAL); 281 282 mlink = mt76_alloc_mlink(dev, mvif); 283 if (!mlink) 284 return ERR_PTR(-ENOMEM); 285 286 mlink->offchannel = true; 287 ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink); 288 if (ret) { 289 kfree(mlink); 290 return ERR_PTR(ret); 291 } 292 rcu_assign_pointer(mvif->offchannel_link, mlink); 293 294 return mlink; 295 } 296 297 void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, 298 struct mt76_vif_link *mlink) 299 { 300 struct mt76_dev *dev = phy->dev; 301 struct mt76_vif_data *mvif; 302 303 if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel) 304 return; 305 306 mvif = mlink->mvif; 307 308 rcu_assign_pointer(mvif->offchannel_link, NULL); 309 dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink); 310 kfree(mlink); 311 } 312 313 void mt76_roc_complete(struct mt76_phy *phy) 314 { 315 struct mt76_vif_link *mlink = phy->roc_link; 316 struct mt76_dev *dev = phy->dev; 317 318 if (!phy->roc_vif) 319 return; 320 321 if (mlink) 322 mlink->mvif->roc_phy = NULL; 323 if (phy->chanctx && phy->main_chandef.chan && phy->offchannel && 324 !test_bit(MT76_MCU_RESET, &dev->phy.state)) { 325 __mt76_set_channel(phy, &phy->main_chandef, false); 326 mt76_offchannel_notify(phy, false); 327 } 328 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link); 329 phy->roc_vif = NULL; 330 phy->roc_link = NULL; 331 if (!test_bit(MT76_MCU_RESET, &dev->phy.state)) 332 ieee80211_remain_on_channel_expired(phy->hw); 333 } 334 335 void mt76_roc_complete_work(struct work_struct *work) 336 { 337 struct mt76_phy *phy = container_of(work, struct mt76_phy, roc_work.work); 338 struct mt76_dev *dev = phy->dev; 339 340 mutex_lock(&dev->mutex); 341 mt76_roc_complete(phy); 342 mutex_unlock(&dev->mutex); 343 } 344 345 void mt76_abort_roc(struct mt76_phy *phy) 346 { 347 struct mt76_dev *dev = phy->dev; 348 349 cancel_delayed_work_sync(&phy->roc_work); 350 351 mutex_lock(&dev->mutex); 352 mt76_roc_complete(phy); 353 mutex_unlock(&dev->mutex); 354 } 355 EXPORT_SYMBOL_GPL(mt76_abort_roc); 356 357 int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 358 struct ieee80211_channel *chan, int duration, 359 enum ieee80211_roc_type type) 360 { 361 struct cfg80211_chan_def chandef = {}; 362 struct mt76_phy *phy = hw->priv; 363 struct mt76_dev *dev = phy->dev; 364 struct mt76_vif_link *mlink; 365 bool offchannel; 366 int ret = 0; 367 368 phy = dev->band_phys[chan->band]; 369 if (!phy) 370 return -EINVAL; 371 372 cancel_delayed_work_sync(&phy->mac_work); 373 374 mutex_lock(&dev->mutex); 375 376 if (phy->roc_vif || dev->scan.phy == phy || 377 test_bit(MT76_MCU_RESET, &dev->phy.state)) { 378 ret = -EBUSY; 379 goto out; 380 } 381 382 mlink = mt76_get_vif_phy_link(phy, vif); 383 if (IS_ERR(mlink)) { 384 ret = PTR_ERR(mlink); 385 goto out; 386 } 387 388 mlink->mvif->roc_phy = phy; 389 phy->roc_vif = vif; 390 phy->roc_link = mlink; 391 392 offchannel = mt76_offchannel_chandef(phy, chan, &chandef); 393 if (offchannel) 394 mt76_offchannel_notify(phy, true); 395 ret = __mt76_set_channel(phy, &chandef, offchannel); 396 if (ret) { 397 mlink->mvif->roc_phy = NULL; 398 phy->roc_vif = NULL; 399 phy->roc_link = NULL; 400 mt76_put_vif_phy_link(phy, vif, mlink); 401 goto out; 402 } 403 ieee80211_ready_on_channel(hw); 404 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work, 405 msecs_to_jiffies(duration)); 406 407 out: 408 mutex_unlock(&dev->mutex); 409 return ret; 410 } 411 EXPORT_SYMBOL_GPL(mt76_remain_on_channel); 412 413 int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, 414 struct ieee80211_vif *vif) 415 { 416 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 417 struct mt76_vif_data *mvif = mlink->mvif; 418 struct mt76_phy *phy = mvif->roc_phy; 419 420 if (!phy) 421 return 0; 422 423 mt76_abort_roc(phy); 424 425 return 0; 426 } 427 EXPORT_SYMBOL_GPL(mt76_cancel_remain_on_channel); 428