Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19 416 lines 9.9 kB view raw
1// SPDX-License-Identifier: BSD-3-Clause-Clear 2/* 3 * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name> 4 */ 5#include "mt76.h" 6 7static struct mt76_vif_link * 8mt76_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 21static int 22mt76_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 32int 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} 56EXPORT_SYMBOL_GPL(mt76_add_chanctx); 57 58void 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} 77EXPORT_SYMBOL_GPL(mt76_remove_chanctx); 78 79void 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 cancel_delayed_work_sync(&phy->mac_work); 92 93 mutex_lock(&dev->mutex); 94 mt76_phy_update_channel(phy, conf); 95 mutex_unlock(&dev->mutex); 96} 97EXPORT_SYMBOL_GPL(mt76_change_chanctx); 98 99 100int mt76_assign_vif_chanctx(struct ieee80211_hw *hw, 101 struct ieee80211_vif *vif, 102 struct ieee80211_bss_conf *link_conf, 103 struct ieee80211_chanctx_conf *conf) 104{ 105 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 106 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 107 struct mt76_vif_data *mvif = mlink->mvif; 108 int link_id = link_conf->link_id; 109 struct mt76_phy *phy = ctx->phy; 110 struct mt76_dev *dev = phy->dev; 111 bool mlink_alloc = false; 112 int ret = 0; 113 114 if (dev->scan.vif == vif) 115 mt76_abort_scan(dev); 116 117 mutex_lock(&dev->mutex); 118 119 if (vif->type == NL80211_IFTYPE_MONITOR && 120 is_zero_ether_addr(vif->addr)) 121 goto out; 122 123 mlink = mt76_vif_conf_link(dev, vif, link_conf); 124 if (!mlink) { 125 mlink = mt76_alloc_mlink(dev, mvif); 126 if (!mlink) { 127 ret = -ENOMEM; 128 goto out; 129 } 130 mlink_alloc = true; 131 } 132 133 mlink->ctx = conf; 134 ret = dev->drv->vif_link_add(phy, vif, link_conf, mlink); 135 if (ret) { 136 if (mlink_alloc) 137 kfree(mlink); 138 goto out; 139 } 140 141 if (link_conf != &vif->bss_conf) 142 rcu_assign_pointer(mvif->link[link_id], mlink); 143 144out: 145 mutex_unlock(&dev->mutex); 146 147 return ret; 148} 149EXPORT_SYMBOL_GPL(mt76_assign_vif_chanctx); 150 151void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw, 152 struct ieee80211_vif *vif, 153 struct ieee80211_bss_conf *link_conf, 154 struct ieee80211_chanctx_conf *conf) 155{ 156 struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv; 157 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 158 struct mt76_vif_data *mvif = mlink->mvif; 159 int link_id = link_conf->link_id; 160 struct mt76_phy *phy = ctx->phy; 161 struct mt76_dev *dev = phy->dev; 162 163 if (dev->scan.vif == vif) 164 mt76_abort_scan(dev); 165 166 mutex_lock(&dev->mutex); 167 168 if (vif->type == NL80211_IFTYPE_MONITOR && 169 is_zero_ether_addr(vif->addr)) 170 goto out; 171 172 mlink = mt76_vif_conf_link(dev, vif, link_conf); 173 if (!mlink) 174 goto out; 175 176 if (mlink != (struct mt76_vif_link *)vif->drv_priv) 177 rcu_assign_pointer(mvif->link[link_id], NULL); 178 179 dev->drv->vif_link_remove(phy, vif, link_conf, mlink); 180 mlink->ctx = NULL; 181 182 if (mlink != (struct mt76_vif_link *)vif->drv_priv) 183 kfree_rcu(mlink, rcu_head); 184 185out: 186 mutex_unlock(&dev->mutex); 187} 188EXPORT_SYMBOL_GPL(mt76_unassign_vif_chanctx); 189 190int mt76_switch_vif_chanctx(struct ieee80211_hw *hw, 191 struct ieee80211_vif_chanctx_switch *vifs, 192 int n_vifs, 193 enum ieee80211_chanctx_switch_mode mode) 194{ 195 struct mt76_chanctx *old_ctx = (struct mt76_chanctx *)vifs->old_ctx->drv_priv; 196 struct mt76_chanctx *new_ctx = (struct mt76_chanctx *)vifs->new_ctx->drv_priv; 197 struct ieee80211_chanctx_conf *conf = vifs->new_ctx; 198 struct mt76_phy *old_phy = old_ctx->phy; 199 struct mt76_phy *phy = hw->priv; 200 struct mt76_dev *dev = phy->dev; 201 struct mt76_vif_link *mlink; 202 bool update_chan; 203 int i, ret = 0; 204 205 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) 206 phy = new_ctx->phy = dev->band_phys[conf->def.chan->band]; 207 else 208 phy = new_ctx->phy; 209 if (!phy) 210 return -EINVAL; 211 212 update_chan = phy->chanctx != new_ctx; 213 if (update_chan) { 214 if (dev->scan.phy == phy) 215 mt76_abort_scan(dev); 216 217 cancel_delayed_work_sync(&phy->mac_work); 218 } 219 220 mutex_lock(&dev->mutex); 221 222 if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && 223 phy != old_phy && old_phy->chanctx == old_ctx) 224 old_phy->chanctx = NULL; 225 226 if (update_chan) 227 ret = mt76_phy_update_channel(phy, vifs->new_ctx); 228 229 if (ret) 230 goto out; 231 232 if (old_phy == phy) 233 goto skip_link_replace; 234 235 for (i = 0; i < n_vifs; i++) { 236 mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); 237 if (!mlink) 238 continue; 239 240 dev->drv->vif_link_remove(old_phy, vifs[i].vif, 241 vifs[i].link_conf, mlink); 242 243 ret = dev->drv->vif_link_add(phy, vifs[i].vif, 244 vifs[i].link_conf, mlink); 245 if (ret) 246 goto out; 247 248 } 249 250skip_link_replace: 251 for (i = 0; i < n_vifs; i++) { 252 mlink = mt76_vif_conf_link(dev, vifs[i].vif, vifs[i].link_conf); 253 if (!mlink) 254 continue; 255 256 mlink->ctx = vifs->new_ctx; 257 } 258 259out: 260 mutex_unlock(&dev->mutex); 261 262 return ret; 263} 264EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx); 265 266struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, 267 struct ieee80211_vif *vif) 268{ 269 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 270 struct mt76_vif_data *mvif = mlink->mvif; 271 struct mt76_dev *dev = phy->dev; 272 int i, ret; 273 274 for (i = 0; i < ARRAY_SIZE(mvif->link); i++) { 275 mlink = mt76_dereference(mvif->link[i], dev); 276 if (!mlink) 277 continue; 278 279 if (mt76_vif_link_phy(mlink) == phy) 280 return mlink; 281 } 282 283 if (!dev->drv->vif_link_add) 284 return ERR_PTR(-EINVAL); 285 286 mlink = mt76_alloc_mlink(dev, mvif); 287 if (!mlink) 288 return ERR_PTR(-ENOMEM); 289 290 mlink->offchannel = true; 291 ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink); 292 if (ret) { 293 kfree(mlink); 294 return ERR_PTR(ret); 295 } 296 rcu_assign_pointer(mvif->offchannel_link, mlink); 297 298 return mlink; 299} 300 301void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, 302 struct mt76_vif_link *mlink) 303{ 304 struct mt76_dev *dev = phy->dev; 305 struct mt76_vif_data *mvif; 306 307 if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel) 308 return; 309 310 mvif = mlink->mvif; 311 312 rcu_assign_pointer(mvif->offchannel_link, NULL); 313 dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink); 314 kfree(mlink); 315} 316 317void mt76_roc_complete(struct mt76_phy *phy) 318{ 319 struct mt76_vif_link *mlink = phy->roc_link; 320 struct mt76_dev *dev = phy->dev; 321 322 if (!phy->roc_vif) 323 return; 324 325 if (mlink) 326 mlink->mvif->roc_phy = NULL; 327 if (phy->main_chandef.chan && 328 !test_bit(MT76_MCU_RESET, &dev->phy.state)) 329 mt76_set_channel(phy, &phy->main_chandef, false); 330 mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link); 331 phy->roc_vif = NULL; 332 phy->roc_link = NULL; 333 if (!test_bit(MT76_MCU_RESET, &dev->phy.state)) 334 ieee80211_remain_on_channel_expired(phy->hw); 335} 336 337void mt76_roc_complete_work(struct work_struct *work) 338{ 339 struct mt76_phy *phy = container_of(work, struct mt76_phy, roc_work.work); 340 struct mt76_dev *dev = phy->dev; 341 342 mutex_lock(&dev->mutex); 343 mt76_roc_complete(phy); 344 mutex_unlock(&dev->mutex); 345} 346 347void mt76_abort_roc(struct mt76_phy *phy) 348{ 349 struct mt76_dev *dev = phy->dev; 350 351 cancel_delayed_work_sync(&phy->roc_work); 352 353 mutex_lock(&dev->mutex); 354 mt76_roc_complete(phy); 355 mutex_unlock(&dev->mutex); 356} 357EXPORT_SYMBOL_GPL(mt76_abort_roc); 358 359int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 360 struct ieee80211_channel *chan, int duration, 361 enum ieee80211_roc_type type) 362{ 363 struct cfg80211_chan_def chandef = {}; 364 struct mt76_phy *phy = hw->priv; 365 struct mt76_dev *dev = phy->dev; 366 struct mt76_vif_link *mlink; 367 int ret = 0; 368 369 phy = dev->band_phys[chan->band]; 370 if (!phy) 371 return -EINVAL; 372 373 mutex_lock(&dev->mutex); 374 375 if (phy->roc_vif || dev->scan.phy == phy || 376 test_bit(MT76_MCU_RESET, &dev->phy.state)) { 377 ret = -EBUSY; 378 goto out; 379 } 380 381 mlink = mt76_get_vif_phy_link(phy, vif); 382 if (IS_ERR(mlink)) { 383 ret = PTR_ERR(mlink); 384 goto out; 385 } 386 387 mlink->mvif->roc_phy = phy; 388 phy->roc_vif = vif; 389 phy->roc_link = mlink; 390 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); 391 mt76_set_channel(phy, &chandef, true); 392 ieee80211_ready_on_channel(hw); 393 ieee80211_queue_delayed_work(phy->hw, &phy->roc_work, 394 msecs_to_jiffies(duration)); 395 396out: 397 mutex_unlock(&dev->mutex); 398 return ret; 399} 400EXPORT_SYMBOL_GPL(mt76_remain_on_channel); 401 402int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, 403 struct ieee80211_vif *vif) 404{ 405 struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; 406 struct mt76_vif_data *mvif = mlink->mvif; 407 struct mt76_phy *phy = mvif->roc_phy; 408 409 if (!phy) 410 return 0; 411 412 mt76_abort_roc(phy); 413 414 return 0; 415} 416EXPORT_SYMBOL_GPL(mt76_cancel_remain_on_channel);