wifi: mt76: mt7921: introduce chanctx support
The firmware can have the capability to manage the channel context scheduling on multiple roles running on the device including Station, AP and P2P GC/GO mode (will be extended based on the future patchset) to help users sharing the network with others on a single device. The firmware is able to support the channel chanctx up to 2 interface simultaneously running on the different channels. Another thing to be noted is that before the driver is going sent out the management frames, the driver has to get the privilege from the firmware to occupy the current channel context until the frame handshake is completed and then get the privilege back to the firmware. Co-developed-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
034ae28b56
commit
41ac53c899
7 changed files with 157 additions and 17 deletions
|
@ -26,6 +26,27 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
|||
.max_interfaces = MT7921_MAX_INTERFACES,
|
||||
.num_different_channels = 1,
|
||||
.beacon_int_infra_match = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION),
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination if_comb_chanctx[] = {
|
||||
{
|
||||
.limits = if_limits_chanctx,
|
||||
.n_limits = ARRAY_SIZE(if_limits_chanctx),
|
||||
.max_interfaces = 2,
|
||||
.num_different_channels = 2,
|
||||
.beacon_int_infra_match = false,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -66,17 +87,19 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
|||
hw->sta_data_size = sizeof(struct mt7921_sta);
|
||||
hw->vif_data_size = sizeof(struct mt7921_vif);
|
||||
|
||||
if (dev->fw_features & MT7921_FW_CAP_CNM)
|
||||
if (dev->fw_features & MT7921_FW_CAP_CNM) {
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
else
|
||||
wiphy->iface_combinations = if_comb_chanctx;
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
|
||||
} else {
|
||||
wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
|
||||
wiphy->iface_combinations = if_comb;
|
||||
wiphy->iface_combinations = if_comb;
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
}
|
||||
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
|
||||
WIPHY_FLAG_4ADDR_STATION);
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
|
||||
wiphy->max_scan_ssids = 4;
|
||||
|
|
|
@ -168,14 +168,6 @@ static void
|
|||
mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy,
|
||||
struct mt76_rx_status *status, u8 chfreq)
|
||||
{
|
||||
if (!test_bit(MT76_HW_SCANNING, &mphy->state) &&
|
||||
!test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) &&
|
||||
!test_bit(MT76_STATE_ROC, &mphy->state)) {
|
||||
status->freq = mphy->chandef.chan->center_freq;
|
||||
status->band = mphy->chandef.chan->band;
|
||||
return;
|
||||
}
|
||||
|
||||
if (chfreq > 180) {
|
||||
status->band = NL80211_BAND_6GHZ;
|
||||
chfreq = (chfreq - 181) * 4 + 1;
|
||||
|
|
|
@ -858,7 +858,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
|
||||
true, NULL);
|
||||
true, mvif->ctx);
|
||||
|
||||
mt7921_mac_wtbl_update(dev, msta->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
@ -891,7 +891,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
if (!sta->tdls)
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
|
||||
&mvif->sta.wcid, false,
|
||||
NULL);
|
||||
mvif->ctx);
|
||||
}
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
|
@ -1645,7 +1645,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
mt7921_mutex_acquire(dev);
|
||||
|
||||
err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
|
||||
true, NULL);
|
||||
true, mvif->ctx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -1677,12 +1677,108 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
goto out;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
|
||||
NULL);
|
||||
mvif->ctx);
|
||||
|
||||
out:
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static void mt7921_ctx_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct ieee80211_chanctx_conf *ctx = priv;
|
||||
|
||||
if (ctx != mvif->ctx)
|
||||
return;
|
||||
|
||||
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
|
||||
mt7921_mutex_acquire(phy->dev);
|
||||
ieee80211_iterate_active_interfaces(phy->mt76->hw,
|
||||
IEEE80211_IFACE_ITER_ACTIVE,
|
||||
mt7921_ctx_iter, ctx);
|
||||
mt7921_mutex_release(phy->dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mvif->ctx = ctx;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mvif->ctx = NULL;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_prep_tx_info *info)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
u16 duration = info->duration ? info->duration :
|
||||
jiffies_to_msecs(HZ);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
|
||||
MT7921_ROC_REQ_JOIN);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_prep_tx_info *info)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_abort_roc(mvif->phy, mvif);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
.tx = mt7921_tx,
|
||||
.start = mt7921_start,
|
||||
|
@ -1735,6 +1831,13 @@ const struct ieee80211_ops mt7921_ops = {
|
|||
.set_sar_specs = mt7921_set_sar_specs,
|
||||
.remain_on_channel = mt7921_remain_on_channel,
|
||||
.cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
|
||||
.add_chanctx = mt7921_add_chanctx,
|
||||
.remove_chanctx = mt7921_remove_chanctx,
|
||||
.change_chanctx = mt7921_change_chanctx,
|
||||
.assign_vif_chanctx = mt7921_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = mt7921_unassign_vif_chanctx,
|
||||
.mgd_prepare_tx = mt7921_mgd_prepare_tx,
|
||||
.mgd_complete_tx = mt7921_mgd_complete_tx,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt7921_ops);
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ struct mt7921_vif {
|
|||
struct ewma_rssi rssi;
|
||||
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
};
|
||||
|
||||
struct mib_stats {
|
||||
|
|
|
@ -297,6 +297,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
|
||||
|
|
|
@ -140,6 +140,13 @@ static int mt7921s_probe(struct sdio_func *func,
|
|||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
|
||||
|
|
|
@ -218,6 +218,13 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
if (!(features & MT7921_FW_CAP_CNM)) {
|
||||
ops->remain_on_channel = NULL;
|
||||
ops->cancel_remain_on_channel = NULL;
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
ops->mgd_prepare_tx = NULL;
|
||||
ops->mgd_complete_tx = NULL;
|
||||
}
|
||||
|
||||
ops->stop = mt7921u_stop;
|
||||
|
|
Loading…
Add table
Reference in a new issue