.max = 1,
.types = BIT(NL80211_IFTYPE_ADHOC)
}, {
- .max = MT7915_MAX_INTERFACES,
+ .max = 16,
.types = BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
- BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_MESH_POINT)
#endif
- BIT(NL80211_IFTYPE_STATION)
+ }, {
+ .max = MT7915_MAX_INTERFACES,
+ .types = BIT(NL80211_IFTYPE_STATION)
}
};
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
- .max_interfaces = 4,
+ .max_interfaces = MT7915_MAX_INTERFACES,
.num_different_channels = 1,
.beacon_int_infra_match = true,
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
mutex_unlock(&dev->mt76.mutex);
}
-static int get_omac_idx(enum nl80211_iftype type, u32 mask)
+static inline int get_free_idx(u32 mask, u8 start, u8 end)
+{
+ return ffs(~mask & GENMASK(end, start));
+}
+
+static int get_omac_idx(enum nl80211_iftype type, u64 mask)
{
int i;
switch (type) {
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ /* prefer hw bssid slot 1-3 */
+ i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3);
+ if (i)
+ return i - 1;
+
+ if (type != NL80211_IFTYPE_STATION)
+ break;
+
+ /* next, try to find a free repeater entry for the sta */
+ i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
+ REPEATER_BSSID_MAX - REPEATER_BSSID_START);
+ if (i)
+ return i + 32 - 1;
+
+ i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
+ if (i)
+ return i - 1;
+
+ if (~mask & BIT(HW_BSSID_0))
+ return HW_BSSID_0;
+
+ break;
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP:
/* ap uses hw bssid 0 and ext bssid */
if (~mask & BIT(HW_BSSID_0))
return HW_BSSID_0;
- for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++)
- if (~mask & BIT(i))
- return i;
- break;
- case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_STATION:
- /* station uses hw bssid other than 0 */
- for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++)
- if (~mask & BIT(i))
- return i;
+ i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
+ if (i)
+ return i - 1;
+
break;
default:
WARN_ON(1);
else
mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS;
- ret = mt7915_mcu_add_dev_info(dev, vif, true);
+ ret = mt7915_mcu_add_dev_info(phy, vif, true);
if (ret)
goto out;
phy->mt76->vif_mask |= BIT(mvif->idx);
- phy->omac_mask |= BIT(mvif->omac_idx);
+ phy->omac_mask |= BIT_ULL(mvif->omac_idx);
idx = MT7915_WTBL_RESERVED - mvif->idx;
mtxq->wcid = &mvif->sta.wcid;
}
+ if (vif->type != NL80211_IFTYPE_AP &&
+ (!mvif->omac_idx || mvif->omac_idx > 3))
+ vif->offload_flags = 0;
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
out:
/* TODO: disable beacon for the bss */
- mt7915_mcu_add_dev_info(dev, vif, false);
+ mt7915_mcu_add_dev_info(phy, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
sync->enable = true;
}
+static int
+mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+ bool bssid, bool enable)
+{
+ struct mt7915_dev *dev = phy->dev;
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ u32 idx = mvif->omac_idx - REPEATER_BSSID_START;
+ u32 mask = phy->omac_mask >> 32 & ~BIT(idx);
+ const u8 *addr = vif->addr;
+ struct {
+ u8 mode;
+ u8 force_clear;
+ u8 clear_bitmap[8];
+ u8 entry_count;
+ u8 write;
+ u8 band;
+
+ u8 index;
+ u8 bssid;
+ u8 addr[ETH_ALEN];
+ } __packed req = {
+ .mode = !!mask || enable,
+ .entry_count = 1,
+ .write = 1,
+
+ .index = idx * 2 + bssid,
+ };
+
+ if (bssid)
+ addr = vif->bss_conf.bssid;
+
+ if (enable)
+ ether_addr_copy(req.addr, addr);
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MUAR_UPDATE,
+ &req, sizeof(req), true);
+}
+
int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
struct ieee80211_vif *vif, int enable)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct sk_buff *skb;
+ if (mvif->omac_idx >= REPEATER_BSSID_START)
+ mt7915_mcu_muar_config(phy, vif, true, enable);
+
skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL,
MT7915_BSS_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
if (vif->bss_conf.he_support)
mt7915_mcu_bss_he_tlv(skb, vif, phy);
- if (mvif->omac_idx > HW_BSSID_MAX)
- mt7915_mcu_bss_ext_tlv(skb, mvif);
- else
+ if (mvif->omac_idx < EXT_BSSID_START)
mt7915_mcu_bss_sync_tlv(skb, vif);
+ else if (mvif->omac_idx < REPEATER_BSSID_START)
+ mt7915_mcu_bss_ext_tlv(skb, mvif);
}
return __mt76_mcu_skb_send_msg(&phy->dev->mt76, skb,
MCU_EXT_CMD_STA_REC_UPDATE, true);
}
-int mt7915_mcu_add_dev_info(struct mt7915_dev *dev,
+int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,
struct ieee80211_vif *vif, bool enable)
{
+ struct mt7915_dev *dev = phy->dev;
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct {
struct req_hdr {
},
};
+ if (mvif->omac_idx >= REPEATER_BSSID_START)
+ return mt7915_mcu_muar_config(phy, vif, false, enable);
+
memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN);
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE,
&data, sizeof(data), true);
MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
MCU_EXT_CMD_RX_HDR_TRANS = 0x47,
+ MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_SET_RX_PATH = 0x4e,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
#include "../mt76.h"
#include "regs.h"
-#define MT7915_MAX_INTERFACES 4
+#define MT7915_MAX_INTERFACES 32
#define MT7915_MAX_WMM_SETS 4
#define MT7915_WTBL_SIZE 288
#define MT7915_WTBL_RESERVED (MT7915_WTBL_SIZE - 1)
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
u32 rxfilter;
- u32 omac_mask;
+ u64 omac_mask;
u16 noise;
u16 chainmask;
HW_BSSID_1,
HW_BSSID_2,
HW_BSSID_3,
- HW_BSSID_MAX,
+ HW_BSSID_MAX = HW_BSSID_3,
EXT_BSSID_START = 0x10,
EXT_BSSID_1,
- EXT_BSSID_2,
- EXT_BSSID_3,
- EXT_BSSID_4,
- EXT_BSSID_5,
- EXT_BSSID_6,
- EXT_BSSID_7,
- EXT_BSSID_8,
- EXT_BSSID_9,
- EXT_BSSID_10,
- EXT_BSSID_11,
- EXT_BSSID_12,
- EXT_BSSID_13,
- EXT_BSSID_14,
- EXT_BSSID_15,
- EXT_BSSID_END
+ EXT_BSSID_15 = 0x1f,
+ EXT_BSSID_MAX = EXT_BSSID_15,
+ REPEATER_BSSID_START = 0x20,
+ REPEATER_BSSID_MAX = 0x3f,
};
enum {
void mt7915_dma_prefetch(struct mt7915_dev *dev);
void mt7915_dma_cleanup(struct mt7915_dev *dev);
int mt7915_mcu_init(struct mt7915_dev *dev);
-int mt7915_mcu_add_dev_info(struct mt7915_dev *dev,
+int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,
struct ieee80211_vif *vif, bool enable);
int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
struct ieee80211_vif *vif, int enable);