static int mt76_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt76_dev *dev = hw->priv; struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; unsigned int idx = 0; int ret = 0; if (vif->addr[0] & BIT(1)) idx = 1 + (((dev->macaddr[0] ^ vif->addr[0]) >> 2) & 7); /* * Client mode typically only has one configurable BSSID register, * which is used for bssidx=0. This is linked to the MAC address. * Since mac80211 allows changing interface types, and we cannot * force the use of the primary MAC address for a station mode * interface, we need some other way of configuring a per-interface * remote BSSID. * The hardware provides an AP-Client feature, where bssidx 0-7 are * used for AP mode and bssidx 8-15 for client mode. * We shift the station interface bss index by 8 to force the * hardware to recognize the BSSID. * The resulting bssidx mismatch for unicast frames is ignored by hw. */ if (vif->type == NL80211_IFTYPE_STATION) idx += 8; mvif->idx = idx; mvif->group_wcid.idx = 254 - idx; mvif->group_wcid.hw_key_idx = -1; mt76_txq_init(dev, vif->txq); return ret; }
static int mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int ret; int i; mutex_lock(&dev->mutex); ret = dev->drv->sta_add(dev, vif, sta); if (ret) goto out; for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { struct mt76_txq *mtxq; if (!sta->txq[i]) continue; mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; mtxq->wcid = wcid; mt76_txq_init(dev, sta->txq[i]); } ewma_signal_init(&wcid->rssi); rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: mutex_unlock(&dev->mutex); return ret; }
static int mt76_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt76_dev *dev = hw->priv; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv; int ret = 0; int idx = 0; int i; mutex_lock(&dev->mutex); idx = mt76_wcid_alloc(dev); if (idx < 0) { ret = -ENOSPC; goto out; } msta->wcid.idx = idx; msta->wcid.hw_key_idx = -1; mt76_mac_wcid_setup(dev, idx, mvif->idx, sta->addr); mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx)); for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt76_txq_init(dev, sta->txq[i]); rcu_assign_pointer(dev->wcid[idx], &msta->wcid); out: mutex_unlock(&dev->mutex); return ret; }
static void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, unsigned int idx) { struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76_txq *mtxq; memset(mvif, 0, sizeof(*mvif)); mvif->idx = idx; mvif->group_wcid.idx = MT_VIF_WCID(idx); mvif->group_wcid.hw_key_idx = -1; mtxq = (struct mt76_txq *) vif->txq->drv_priv; mtxq->wcid = &mvif->group_wcid; mt76_txq_init(&dev->mt76, vif->txq); }
static void mt7603_txq_init(struct mt7603_dev *dev, struct ieee80211_txq *txq) { struct mt76_txq *mtxq; if (!txq) return; mtxq = (struct mt76_txq *) txq->drv_priv; if (txq->sta) { struct mt7603_sta *sta = (struct mt7603_sta *) txq->sta->drv_priv; mtxq->wcid = &sta->wcid; } else { struct mt7603_vif *mvif = (struct mt7603_vif *) txq->vif->drv_priv; mtxq->wcid = &mvif->sta.wcid; } mt76_txq_init(&dev->mt76, txq); }