Skip to content

Commit 4f44d32

Browse files
committed
Merge tag 'wireless-2023-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Kalle Valo says: ==================== wireless fixes for v6.3 Third set of fixes for v6.3. mt76 has two kernel crash fixes and adding back 160 MHz channel support for mt7915. mac80211 has fixes for a race in transmit path and two mesh related fixes. iwlwifi also has fixes for races. * tag 'wireless-2023-03-23' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: mac80211: fix mesh path discovery based on unicast packets wifi: mac80211: fix qos on mesh interfaces wifi: iwlwifi: mvm: protect TXQ list manipulation wifi: iwlwifi: mvm: fix mvmtxq->stopped handling wifi: mac80211: Serialize ieee80211_handle_wake_tx_queue() wifi: mwifiex: mark OF related data as maybe unused wifi: mt76: connac: do not check WED status for non-mmio devices wifi: mt76: mt7915: add back 160MHz channel width support for MT7915 wifi: mt76: do not run mt76_unregister_device() on unregistered hw ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents b1de5c7 + f355f70 commit 4f44d32

File tree

15 files changed

+119
-64
lines changed

15 files changed

+119
-64
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
732732

733733
rcu_read_lock();
734734
do {
735-
while (likely(!mvmtxq->stopped &&
735+
while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL,
736+
&mvmtxq->state) &&
737+
!test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
738+
&mvmtxq->state) &&
736739
!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
737740
skb = ieee80211_tx_dequeue(hw, txq);
738741

@@ -757,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
757760
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
758761
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
759762

760-
/*
761-
* Please note that racing is handled very carefully here:
762-
* mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
763-
* deleted afterwards.
764-
* This means that if:
765-
* mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
766-
* queue is allocated and we can TX.
767-
* mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
768-
* a race, should defer the frame.
769-
* mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
770-
* need to allocate the queue and defer the frame.
771-
* mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
772-
* queue is already scheduled for allocation, no need to allocate,
773-
* should defer the frame.
774-
*/
775-
776-
/* If the queue is allocated TX and return. */
777-
if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
778-
/*
779-
* Check that list is empty to avoid a race where txq_id is
780-
* already updated, but the queue allocation work wasn't
781-
* finished
782-
*/
783-
if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
784-
return;
785-
763+
if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
764+
!txq->sta) {
786765
iwl_mvm_mac_itxq_xmit(hw, txq);
787766
return;
788767
}
789768

790-
/* The list is being deleted only after the queue is fully allocated. */
791-
if (!list_empty(&mvmtxq->list))
792-
return;
769+
/* iwl_mvm_mac_itxq_xmit() will later be called by the worker
770+
* to handle any packets we leave on the txq now
771+
*/
793772

794-
list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
795-
schedule_work(&mvm->add_stream_wk);
773+
spin_lock_bh(&mvm->add_stream_lock);
774+
/* The list is being deleted only after the queue is fully allocated. */
775+
if (list_empty(&mvmtxq->list) &&
776+
/* recheck under lock */
777+
!test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) {
778+
list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
779+
schedule_work(&mvm->add_stream_wk);
780+
}
781+
spin_unlock_bh(&mvm->add_stream_lock);
796782
}
797783

798784
#define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,10 @@ struct iwl_mvm_txq {
729729
struct list_head list;
730730
u16 txq_id;
731731
atomic_t tx_request;
732-
bool stopped;
732+
#define IWL_MVM_TXQ_STATE_STOP_FULL 0
733+
#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1
734+
#define IWL_MVM_TXQ_STATE_READY 2
735+
unsigned long state;
733736
};
734737

735738
static inline struct iwl_mvm_txq *
@@ -827,6 +830,7 @@ struct iwl_mvm {
827830
struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
828831
};
829832
struct work_struct add_stream_wk; /* To add streams to queues */
833+
spinlock_t add_stream_lock;
830834

831835
const char *nvm_file_name;
832836
struct iwl_nvm_data *nvm_data;

drivers/net/wireless/intel/iwlwifi/mvm/ops.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
11951195
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
11961196
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
11971197
INIT_LIST_HEAD(&mvm->add_stream_txqs);
1198+
spin_lock_init(&mvm->add_stream_lock);
11981199

11991200
init_waitqueue_head(&mvm->rx_sync_waitq);
12001201

@@ -1691,7 +1692,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
16911692

16921693
txq = sta->txq[tid];
16931694
mvmtxq = iwl_mvm_txq_from_mac80211(txq);
1694-
mvmtxq->stopped = !start;
1695+
if (start)
1696+
clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
1697+
else
1698+
set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
16951699

16961700
if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
16971701
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);

drivers/net/wireless/intel/iwlwifi/mvm/sta.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
384384
struct iwl_mvm_txq *mvmtxq =
385385
iwl_mvm_txq_from_tid(sta, tid);
386386

387-
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
387+
spin_lock_bh(&mvm->add_stream_lock);
388388
list_del_init(&mvmtxq->list);
389+
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
390+
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
391+
spin_unlock_bh(&mvm->add_stream_lock);
389392
}
390393

391394
/* Regardless if this is a reserved TXQ for a STA - mark it as false */
@@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
479482
disable_agg_tids |= BIT(tid);
480483
mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
481484

482-
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
485+
spin_lock_bh(&mvm->add_stream_lock);
483486
list_del_init(&mvmtxq->list);
487+
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
488+
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
489+
spin_unlock_bh(&mvm->add_stream_lock);
484490
}
485491

486492
mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
@@ -693,7 +699,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
693699
queue, iwl_mvm_ac_to_tx_fifo[ac]);
694700

695701
/* Stop the queue and wait for it to empty */
696-
txq->stopped = true;
702+
set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
697703

698704
ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
699705
if (ret) {
@@ -736,7 +742,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
736742

737743
out:
738744
/* Continue using the queue */
739-
txq->stopped = false;
745+
clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
740746

741747
return ret;
742748
}
@@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
14441450
* a queue in the function itself.
14451451
*/
14461452
if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) {
1453+
spin_lock_bh(&mvm->add_stream_lock);
14471454
list_del_init(&mvmtxq->list);
1455+
spin_unlock_bh(&mvm->add_stream_lock);
14481456
continue;
14491457
}
14501458

1451-
list_del_init(&mvmtxq->list);
1459+
/* now we're ready, any remaining races/concurrency will be
1460+
* handled in iwl_mvm_mac_itxq_xmit()
1461+
*/
1462+
set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
1463+
14521464
local_bh_disable();
1465+
spin_lock(&mvm->add_stream_lock);
1466+
list_del_init(&mvmtxq->list);
1467+
spin_unlock(&mvm->add_stream_lock);
1468+
14531469
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
14541470
local_bh_enable();
14551471
}
@@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
18641880
struct iwl_mvm_txq *mvmtxq =
18651881
iwl_mvm_txq_from_mac80211(sta->txq[i]);
18661882

1883+
spin_lock_bh(&mvm->add_stream_lock);
18671884
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
18681885
list_del_init(&mvmtxq->list);
1886+
clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
1887+
spin_unlock_bh(&mvm->add_stream_lock);
18691888
}
18701889
}
18711890

drivers/net/wireless/marvell/mwifiex/pcie.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
172172
.can_ext_scan = true,
173173
};
174174

175-
static const struct of_device_id mwifiex_pcie_of_match_table[] = {
175+
static const struct of_device_id mwifiex_pcie_of_match_table[] __maybe_unused = {
176176
{ .compatible = "pci11ab,2b42" },
177177
{ .compatible = "pci1b4b,2b42" },
178178
{ }

drivers/net/wireless/marvell/mwifiex/sdio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
495495
{"EXTLAST", NULL, 0, 0xFE},
496496
};
497497

498-
static const struct of_device_id mwifiex_sdio_of_match_table[] = {
498+
static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = {
499499
{ .compatible = "marvell,sd8787" },
500500
{ .compatible = "marvell,sd8897" },
501501
{ .compatible = "marvell,sd8978" },

drivers/net/wireless/mediatek/mt76/mac80211.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
539539
if (ret)
540540
return ret;
541541

542+
set_bit(MT76_STATE_REGISTERED, &phy->state);
542543
phy->dev->phys[phy->band_idx] = phy;
543544

544545
return 0;
@@ -549,6 +550,9 @@ void mt76_unregister_phy(struct mt76_phy *phy)
549550
{
550551
struct mt76_dev *dev = phy->dev;
551552

553+
if (!test_bit(MT76_STATE_REGISTERED, &phy->state))
554+
return;
555+
552556
if (IS_ENABLED(CONFIG_MT76_LEDS))
553557
mt76_led_cleanup(phy);
554558
mt76_tx_status_check(dev, true);
@@ -719,6 +723,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
719723
return ret;
720724

721725
WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
726+
set_bit(MT76_STATE_REGISTERED, &phy->state);
722727
sched_set_fifo_low(dev->tx_worker.task);
723728

724729
return 0;
@@ -729,6 +734,9 @@ void mt76_unregister_device(struct mt76_dev *dev)
729734
{
730735
struct ieee80211_hw *hw = dev->hw;
731736

737+
if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state))
738+
return;
739+
732740
if (IS_ENABLED(CONFIG_MT76_LEDS))
733741
mt76_led_cleanup(&dev->phy);
734742
mt76_tx_status_check(dev, true);

drivers/net/wireless/mediatek/mt76/mt76.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ struct mt76_tx_cb {
402402

403403
enum {
404404
MT76_STATE_INITIALIZED,
405+
MT76_STATE_REGISTERED,
405406
MT76_STATE_RUNNING,
406407
MT76_STATE_MCU_RUNNING,
407408
MT76_SCANNING,

drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,9 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv);
12211221

12221222
int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb)
12231223
{
1224+
if (!mt76_is_mmio(dev))
1225+
return 0;
1226+
12241227
if (!mtk_wed_device_active(&dev->mmio.wed))
12251228
return 0;
12261229

drivers/net/wireless/mediatek/mt76/mt7915/init.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
383383
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
384384
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
385385
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
386-
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
387386

388387
hw->max_tx_fragments = 4;
389388

@@ -396,26 +395,38 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
396395
}
397396

398397
if (phy->mt76->cap.has_5ghz) {
398+
struct ieee80211_sta_vht_cap *vht_cap;
399+
400+
vht_cap = &phy->mt76->sband_5g.sband.vht_cap;
399401
phy->mt76->sband_5g.sband.ht_cap.cap |=
400402
IEEE80211_HT_CAP_LDPC_CODING |
401403
IEEE80211_HT_CAP_MAX_AMSDU;
402404
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
403405
IEEE80211_HT_MPDU_DENSITY_4;
404406

405407
if (is_mt7915(&dev->mt76)) {
406-
phy->mt76->sband_5g.sband.vht_cap.cap |=
408+
vht_cap->cap |=
407409
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
408410
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
411+
412+
if (!dev->dbdc_support)
413+
vht_cap->cap |=
414+
IEEE80211_VHT_CAP_SHORT_GI_160 |
415+
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
416+
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
409417
} else {
410-
phy->mt76->sband_5g.sband.vht_cap.cap |=
418+
vht_cap->cap |=
411419
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
412420
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
413421

414422
/* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */
415-
phy->mt76->sband_5g.sband.vht_cap.cap |=
423+
vht_cap->cap |=
416424
IEEE80211_VHT_CAP_SHORT_GI_160 |
417425
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
418426
}
427+
428+
if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)
429+
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
419430
}
420431

421432
mt76_set_stream_caps(phy->mt76, true);
@@ -841,9 +852,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
841852
int sts = hweight8(phy->mt76->chainmask);
842853
u8 c, sts_160 = sts;
843854

844-
/* mt7915 doesn't support bw160 */
845-
if (is_mt7915(&dev->mt76))
846-
sts_160 = 0;
855+
/* Can do 1/2 of STS in 160Mhz mode for mt7915 */
856+
if (is_mt7915(&dev->mt76)) {
857+
if (!dev->dbdc_support)
858+
sts_160 /= 2;
859+
else
860+
sts_160 = 0;
861+
}
847862

848863
#ifdef CONFIG_MAC80211_MESH
849864
if (vif == NL80211_IFTYPE_MESH_POINT)
@@ -944,10 +959,15 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
944959
int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
945960
u16 mcs_map = 0;
946961
u16 mcs_map_160 = 0;
947-
u8 nss_160 = nss;
962+
u8 nss_160;
948963

949-
/* Can't do 160MHz with mt7915 */
950-
if (is_mt7915(&dev->mt76))
964+
if (!is_mt7915(&dev->mt76))
965+
nss_160 = nss;
966+
else if (!dev->dbdc_support)
967+
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
968+
nss_160 = nss / 2;
969+
else
970+
/* Can't do 160MHz with mt7915 dbdc */
951971
nss_160 = 0;
952972

953973
for (i = 0; i < 8; i++) {

0 commit comments

Comments
 (0)