mt76: ensure net80211 com instance before returning from driver load

Do as we have done for iwlwifi (f808c43ad9,  bee60c9897) add a
completion event for device registration which calls into 802.11
and creates the wifi "device" (net80211 com instance).
This is needed as otherwise the deferred work in the mt76 drivers
(mt7915, mt7921, mt7925, mt7996; but not the 7615 [*]) would make
driver loading return before the wifi device is there.  We would then
continue, e.g., during rc startup and race possibly trying to create
a vap (wlan interface) with the underlying device not being registered
yet and fail.

[*] the 7615 does not seem to do this asynchronously so is fine.

Sponsored by:	The FreeBSD Foundation
Tested on:	7921, others to be tested at time
MFC after:	3 days
This commit is contained in:
Bjoern A. Zeeb
2026-06-08 06:50:30 +00:00
parent b8ec4929e9
commit baf8561bdc
6 changed files with 33 additions and 0 deletions
+4
View File
@@ -814,6 +814,10 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
set_bit(MT76_STATE_REGISTERED, &phy->state);
sched_set_fifo_low(dev->tx_worker.task);
#if defined(__FreeBSD__)
complete(&dev->drv_start_complete);
#endif
return 0;
}
EXPORT_SYMBOL_GPL(mt76_register_device);
+3
View File
@@ -1026,6 +1026,9 @@ struct mt76_dev {
} test_mtd;
#endif
struct workqueue_struct *wq;
#if defined(__FreeBSD__)
struct completion drv_start_complete;
#endif
union {
struct mt76_mmio mmio;
@@ -862,6 +862,9 @@ mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
INIT_WORK(&dev->init_work, mt7915_init_work);
#if defined(__FreeBSD__)
init_completion(&dev->mt76.drv_start_complete);
#endif
ret = mt7915_dma_init(dev, phy2);
if (ret)
@@ -1298,6 +1301,9 @@ int mt7915_register_device(struct mt7915_dev *dev)
}
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
#if defined(__FreeBSD__)
wait_for_completion(&dev->mt76.drv_start_complete);
#endif
dev->recovery.hw_init_done = true;
@@ -308,6 +308,9 @@ int mt7921_register_device(struct mt792x_dev *dev)
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
INIT_WORK(&dev->init_work, mt7921_init_work);
#if defined(__FreeBSD__)
init_completion(&dev->mt76.drv_start_complete);
#endif
INIT_WORK(&dev->phy.roc_work, mt7921_roc_work);
timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0);
@@ -359,6 +362,10 @@ int mt7921_register_device(struct mt792x_dev *dev)
queue_work(system_percpu_wq, &dev->init_work);
#if defined(__FreeBSD__)
wait_for_completion(&dev->mt76.drv_start_complete);
#endif
return 0;
}
EXPORT_SYMBOL_GPL(mt7921_register_device);
@@ -228,6 +228,9 @@ int mt7925_register_device(struct mt792x_dev *dev)
INIT_WORK(&dev->reset_work, mt7925_mac_reset_work);
INIT_WORK(&dev->init_work, mt7925_init_work);
#if defined(__FreeBSD__)
init_completion(&dev->mt76.drv_start_complete);
#endif
INIT_WORK(&dev->phy.roc_work, mt7925_roc_work);
timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0);
@@ -282,6 +285,10 @@ int mt7925_register_device(struct mt792x_dev *dev)
queue_work(system_percpu_wq, &dev->init_work);
#if defined(__FreeBSD__)
wait_for_completion(&dev->mt76.drv_start_complete);
#endif
return 0;
}
EXPORT_SYMBOL_GPL(mt7925_register_device);
@@ -1222,6 +1222,9 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
}
INIT_WORK(&dev->init_work, mt7996_init_work);
#if defined(__FreeBSD__)
init_completion(&dev->mt76.drv_start_complete);
#endif
INIT_WORK(&dev->wed_rro.work, mt7996_wed_rro_work);
INIT_LIST_HEAD(&dev->wed_rro.poll_list);
spin_lock_init(&dev->wed_rro.lock);
@@ -1736,6 +1739,9 @@ int mt7996_register_device(struct mt7996_dev *dev)
#endif
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
#if defined(__FreeBSD__)
wait_for_completion(&dev->mt76.drv_start_complete);
#endif
dev->recovery.hw_init_done = true;