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.

wifi: mac80211: add a TXQ for management frames on NAN devices

Currently there is no TXQ for non-data frames. Add a new txq_mgmt for
this purpose and create one of these on NAN devices. On NAN devices,
these frames may only be transmitted during the discovery window and it
is therefore helpful to schedule them using a queue.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260326121156.32eddd986bd2.Iee95758287c276155fbd7779d3f263339308e083@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Benjamin Berg and committed by
Johannes Berg
7f0de94e 8ffb33d7

+67 -17
+2
include/net/mac80211.h
··· 2074 2074 * @drv_priv: data area for driver use, will always be aligned to 2075 2075 * sizeof(void \*). 2076 2076 * @txq: the multicast data TX queue 2077 + * @txq_mgmt: the mgmt frame TX queue, currently only exists for NAN devices 2077 2078 * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see 2078 2079 * &enum ieee80211_offload_flags. 2079 2080 */ ··· 2093 2092 u8 hw_queue[IEEE80211_NUM_ACS]; 2094 2093 2095 2094 struct ieee80211_txq *txq; 2095 + struct ieee80211_txq *txq_mgmt; 2096 2096 2097 2097 netdev_features_t netdev_features; 2098 2098 u32 driver_flags;
+26 -2
net/mac80211/iface.c
··· 682 682 if (sdata->vif.txq) 683 683 ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq)); 684 684 685 + if (sdata->vif.txq_mgmt) 686 + ieee80211_txq_purge(sdata->local, 687 + to_txq_info(sdata->vif.txq_mgmt)); 688 + 685 689 sdata->bss = NULL; 686 690 687 691 if (local->open_count == 0) ··· 2227 2223 lockdep_assert_wiphy(local->hw.wiphy); 2228 2224 2229 2225 if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) { 2226 + int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size, 2227 + sizeof(void *)); 2230 2228 struct wireless_dev *wdev; 2229 + int txq_size = 0; 2231 2230 2232 - sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, 2233 - GFP_KERNEL); 2231 + if (type == NL80211_IFTYPE_NAN) 2232 + txq_size = sizeof(struct txq_info) + 2233 + local->hw.txq_data_size; 2234 + 2235 + sdata = kzalloc(size + txq_size, GFP_KERNEL); 2234 2236 if (!sdata) 2235 2237 return -ENOMEM; 2236 2238 wdev = &sdata->wdev; ··· 2246 2236 ieee80211_assign_perm_addr(local, wdev->address, type); 2247 2237 memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); 2248 2238 ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr); 2239 + 2240 + /* 2241 + * Add a management TXQ for NAN devices which includes frames 2242 + * that will only be transmitted during discovery windows (DWs) 2243 + */ 2244 + if (type == NL80211_IFTYPE_NAN) { 2245 + txqi = (struct txq_info *)((unsigned long)sdata + size); 2246 + ieee80211_txq_init(sdata, NULL, txqi, 2247 + IEEE80211_NUM_TIDS); 2248 + } 2249 2249 } else { 2250 2250 int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size, 2251 2251 sizeof(void *)); ··· 2405 2385 2406 2386 if (sdata->vif.txq) 2407 2387 ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq)); 2388 + 2389 + if (sdata->vif.txq_mgmt) 2390 + ieee80211_txq_purge(sdata->local, 2391 + to_txq_info(sdata->vif.txq_mgmt)); 2408 2392 2409 2393 synchronize_rcu(); 2410 2394
+16 -4
net/mac80211/tx.c
··· 1313 1313 unlikely(!ieee80211_is_data_present(hdr->frame_control))) { 1314 1314 if ((!ieee80211_is_mgmt(hdr->frame_control) || 1315 1315 ieee80211_is_bufferable_mmpdu(skb) || 1316 - vif->type == NL80211_IFTYPE_STATION) && 1316 + vif->type == NL80211_IFTYPE_STATION || 1317 + vif->type == NL80211_IFTYPE_NAN || 1318 + vif->type == NL80211_IFTYPE_NAN_DATA) && 1317 1319 sta && sta->uploaded) { 1318 1320 /* 1319 1321 * This will be NULL if the driver didn't set the 1320 1322 * opt-in hardware flag. 1321 1323 */ 1322 1324 txq = sta->sta.txq[IEEE80211_NUM_TIDS]; 1325 + } else if ((!ieee80211_is_mgmt(hdr->frame_control) || 1326 + ieee80211_is_bufferable_mmpdu(skb)) && 1327 + !sta) { 1328 + txq = vif->txq_mgmt; 1323 1329 } 1324 1330 } else if (sta) { 1325 1331 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; ··· 1518 1512 txqi->txq.vif = &sdata->vif; 1519 1513 1520 1514 if (!sta) { 1521 - sdata->vif.txq = &txqi->txq; 1522 - txqi->txq.tid = 0; 1523 - txqi->txq.ac = IEEE80211_AC_BE; 1515 + txqi->txq.tid = tid; 1516 + 1517 + if (tid == IEEE80211_NUM_TIDS) { 1518 + sdata->vif.txq_mgmt = &txqi->txq; 1519 + txqi->txq.ac = IEEE80211_AC_VO; 1520 + } else { 1521 + sdata->vif.txq = &txqi->txq; 1522 + txqi->txq.ac = IEEE80211_AC_BE; 1523 + } 1524 1524 1525 1525 return; 1526 1526 }
+23 -11
net/mac80211/util.c
··· 325 325 struct ieee80211_vif *vif = &sdata->vif; 326 326 struct fq *fq = &local->fq; 327 327 struct ps_data *ps = NULL; 328 - struct txq_info *txqi; 328 + struct txq_info *txqi = NULL; 329 329 struct sta_info *sta; 330 330 int i; 331 331 ··· 344 344 345 345 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { 346 346 struct ieee80211_txq *txq = sta->sta.txq[i]; 347 + struct txq_info *sta_txqi; 347 348 348 349 if (!txq) 349 350 continue; 350 351 351 - txqi = to_txq_info(txq); 352 + sta_txqi = to_txq_info(txq); 352 353 353 354 if (ac != txq->ac) 354 355 continue; 355 356 356 357 if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, 357 - &txqi->flags)) 358 + &sta_txqi->flags)) 358 359 continue; 359 360 360 361 spin_unlock(&fq->lock); 361 - drv_wake_tx_queue(local, txqi); 362 + drv_wake_tx_queue(local, sta_txqi); 362 363 spin_lock(&fq->lock); 363 364 } 364 365 } 365 366 366 - if (!vif->txq) 367 - goto out; 367 + if (vif->txq) { 368 + txqi = to_txq_info(vif->txq); 368 369 369 - txqi = to_txq_info(vif->txq); 370 + /* txq and txq_mgmt are mutually exclusive */ 371 + WARN_ON_ONCE(vif->txq_mgmt); 370 372 371 - if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) || 372 - (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac) 373 - goto out; 373 + if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) || 374 + (ps && atomic_read(&ps->num_sta_ps)) || 375 + ac != vif->txq->ac) 376 + txqi = NULL; 377 + } else if (vif->txq_mgmt) { 378 + txqi = to_txq_info(vif->txq_mgmt); 379 + 380 + if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) || 381 + ac != vif->txq_mgmt->ac) 382 + txqi = NULL; 383 + } 374 384 375 385 spin_unlock(&fq->lock); 376 386 377 - drv_wake_tx_queue(local, txqi); 387 + if (txqi) 388 + drv_wake_tx_queue(local, txqi); 389 + 378 390 local_bh_enable(); 379 391 return; 380 392 out: